工作不到一年,做出了100k系統,老闆給我升職加薪

龍躍十二發表於2020-08-31

看了下自己上一次發技術文還是在6月15日,算了算也是兩個來月了。別怕,短暫的離開,是為了更好的相遇。

來到新公司以後啊,發現公司的搜尋業務是真的太多了,大大小小有幾百個搜尋業務。來了之後得先梳理、熟悉業務,才能有所產出嘛。

但是,在工作了大概一個月的時候,優秀的龍叔發現,這組內的系統優化空間很大啊,簡直可以說巨大啊。

所以說,即便是完善的大公司,機會也是有的,大家在自己的工作崗位上也要好好把握機會。在公司想要得到好的提升,主要有三方面可以發力:

  • 第一、直接業務價值顯著,比如具體的PV、UV值提升了多少個點;
  • 第二、系統架構迭代升級或者重構,間接帶來了使用者體驗、或者業務價值;
  • 第三、技術突破,在某個領域方向上做到技術突破或者創新;

小夥伴們,升職加薪指日可待啊...

這些系統都是歷史包袱沉重啊,是不是感覺歷史包袱這個詞很熟悉,對於去搞一些歷史包袱很沉重的工程,我們慣用的方法是是什麼呢?當然是直接重構

這對於工作不滿一年的龍叔來說還是蠻有挑戰的,但我們不怕,去做更具挑戰性的事,才能更好的鍛鍊我們的能力,才會意義非凡。

反覆思考,反覆琢磨了幾天後,向leader提出了系統重構的大致方案。一般在公司你想做什麼都可以和leader提出來,網際網路公司還是比較open的,但是leader會不會採納你的方案就不一定了。

其實,龍叔對於自己已經畫了很多方案圖,調查很多業務場景、做了很多討論之後做的方案還是蠻有信心的。

做就做好準備,不然就是浪費機會。

好了,接下來就不廢話了,從幾個方面說說這次系統設計:

背景介紹

大家都知道龍叔是做搜尋的,所以這次的系統肯定是和搜尋相關的,先和大家嘮嘮搜尋整體鏈路,搜尋鏈路主要分這幾個部分,給大家畫個圖。

搜尋引擎鏈路都包含這三部分,資料來源、搜尋引擎服務、搜尋業務。是不是很簡單,感覺搜尋也沒那麼難。

搜尋鏈路確實都包括這三部分,但沒我說的那麼簡單,每兩個部分之間鏈路很長,業務非常複雜。舉例說下資料來源到搜尋引擎服務的鏈路。

首先資料來源不是單一資料來源、比如說個電商場景的資料來源,主要有商家商品資料、使用者資料、爬蟲資料等多種資料來源。

我這次要做的鏈路是從資料來源到搜尋引擎服務這一段,簡單點就是資料來源提供的資料,需要結構化之後入到搜尋引擎,這樣搜尋引擎才能提供搜尋服務。

可這資料來源真的是五花八門,提供資料的方式也是五花八門的。

設計步驟

背景基本就介紹到這裡了,接下來就說說設計一個系統的步驟。說實話,畢竟是第一次做系統設計,當時真的是無從下手。不過帥氣的龍su有法寶啊,多請教,多思考,多查資料。

在方案評審之前我已經做了很多方案設計圖,這部分的努力主要是為了通過方案評審,這非常重要,通不過評審,老闆不會讓你做,就沒有資源可以用,這專案就擱淺了。

這部分主要從以下幾個步驟發力:

舊系統摸底。找出舊系統的所有不支援當前業務場景的點,有哪些是對當前業務影響較大的,哪些是對未來業務影響較大的,這些都要細細整理出來。不過這塊我做起來還算輕鬆,舊系統在設計架構上就被我找到很多問題。

可能真的是由於歷史原因吧,以前搜尋是一個BU,現在只是大資料裡的一個組了,這中間經歷了多少改朝換代啊,歷史包袱重的無法揹負了,只能選擇拋棄他了。

從上面的架構圖可以很清晰的看出來這個系統有三個嚴重問題:

第一個、業務層資料到達佇列完全依賴於業務方上報。這本來是件無可厚非的事,你要用搜尋引擎,那就得上報資料來。就好比你用資料庫,你總得把資料存進去吧。

但這事在公司行不通,歷史包袱太沉重。業務方完全不想上報資料,雖然勉強上報,經常增量資料丟失。這一丟失資料導致搜尋出不來。最終還是我們的鍋,這...

總結下,就是業務方不想上報資料、上報資料總是丟失,鍋還得搜尋來背。

第二個、資料處理完成直接交付給資料應用,這個問題蠻嚴重的。資料處理其實意味著會消耗大量的計算資源和時間,而一旦資料應用層服務掛掉或者崩潰,將會導致服務短時間無法恢復。

比如1000w的資料處理需要一個24core機器處理12小時,一旦下游的solr或者RS叢集崩潰,把一份全量資料恢復回來,需要資料處理系統重新計算12小時,這恢復時間誰頂的住啊?

由於第一個問題存在,也就是資料上報容易丟失,所以必須依靠全量資料來恢復丟失的增量,我們的近200個業務基本每天都會做一次全量,這可是大把的計算資源浪費啊。

資源浪費一點倒也還好,但是這異常情況下的資料恢復時間確實是個大問題,使用者可等不及這麼長時間啊。

總結下,就是計算資源浪費,資料應用層服務無法做到無狀態,恢復成本高昂。

第三個、資料處理系統耦合度太高,系統太複雜,維護困難。資料處理一般包括資料清洗和業務組裝,資料清洗可以算作是業務變化較少的,但是業務組裝規則是靈活多變的,這部分經常會由於業務方的變動而產生開發的需求。

業務變動頻繁、業務繁多導致系統變得複雜,系統複雜耦合度還很高,導致這個系統維護和開發成本很大,日常需求開發已經成為難題了。

業務場景調查。搜尋有很多場景,比如電商場景,內容場景,直播場景。場景很多,公司業務形態上也是都有這些,但不是所有的場景都使用了我們的搜尋服務。

要去摸底一下那些沒有使用的為啥沒用,沒用肯定是我們做的不好,摸底的主要目標的就是搞清楚到底哪點不好。深入到業務上去了解,才能更好的設計系統。

新系統設計。前兩步驟已經找到了舊系統缺陷和業務問題,新的系統首先要解決之前的問題,其次就是做一些前瞻性的設計。

新系統設計這塊包括以下幾個步驟:

業務梳理 這塊其實在舊系統摸底和業務調查的時候已經做的差不多了,只需要在精細化的梳理下。

業務抽象 業務抽象指的是一系列的業務問題,抽象為一種通用的解決方案。這塊蠻複雜的,在這塊需要花費大量時間。

技術調研 每一種技術都有他的適用場景。舉個例子,使用搜尋引擎,到底是用solr還是用es、還是自研呢?這就需要你對技術方案有了解,知道這些技術方案的優缺點,最終才能找出適合業務發展的技術方案。

方案探討 好的設計不是一蹴而就的,也不是某個人的智慧象徵。好的設計是一群人智慧的結晶,是一個不斷迭代的產品,所以需要多討論。

方案確定 前面的問題解決了,基本方案差不多也該定下來了。為保證方案不會出現返工情況,你需要再拉上leader開個最終的專案方案評審會加上確定專案排期。

架構圖介紹

說了那麼多好像還沒說到我的設計到底在哪裡,接下里就來說說我的設計。

在整個設計中我也做了好幾版的設計圖,草稿就不放出來了,直接放最終的一版設計方案來說,中間解釋的時候會說那些演進的點。

首先我設計這個系統目標有如下:

  • 零上報 指的是資料不依賴業務方上報,有資料變更立刻感知到
  • 準實時 資料變更之後實時進入引擎,提供搜尋服務
  • 高吞吐
  • 高容錯
  • 低耦合
  • 易維護

這幾個目標已經完全解決了之前系統存在的問題,比如上報資料問題,資源浪費問題,緊急恢復時間長的問題。

整體上我採用了分層設計方案結合微服務的思想,把複雜的問題分層抽象,各層次之間功能單一且分明,耦合度低,維護方便。

當然這樣的設計會導致資料鏈路變得略長,會有多餘的網路傳輸延時。現在的網路卡已經夠大了,網路傳輸在這個專案中不是不足為慮。

自上而下,沿著資料流動的方向,逐層解釋下為何這麼設計:

第一層,業務資料層,這是不變的,一致存在的。目前我們共有快200個業務場景,每個業務方的資料來源是不同的,同時也有交叉的,比如商品資料在類目搜尋、內容搜尋、訂單搜尋、商品推薦上都使用,他們確是不同的業務場景,資料有交叉也有不同。

但其實這裡我們不必太關心業務方的資料來源,不管是何種來源最終都會有一個儲存介質,只需要關心資料實際儲存在哪裡的。

把多種儲存介質抽象出來,用一個服務去監聽這些介質的資料變更行為,這就是接下來的資料監聽層。

第二層,資料監聽層。主要負責監聽變更的業務資料,把變更的資料獲取到,用規定的格式輸出到下游佇列即可。

第三層,資料緩衝層。資料緩衝一般用在系統與系統之間,通常情況下不要讓系統與系統之間直接傳遞資料,這樣的資料傳遞會有很高的風險,得依賴接收端系統的穩定性。

有了資料緩衝,系統之間就不直接互動資料了,系統之間沒什麼依賴關係,也不會互相影響。

第四層,資料處理層。這一層最終需要把零散的、不規則的資料處理為一個搜尋可用的DOC資料。這塊任務蠻艱鉅的,當時在討論這一層的時候,花費了很多時間。

資料處理包括兩部分,一部分是一些通用型處理,比如去html標籤、資料格式int轉string等等處理邏輯;另一部分是一些變化較多的業務部分,比如一個doc有十五個欄位,其中有三個來自A業務,三個來自B業務,而這些來自都是需要實時去業務方拿結果的。再比如對DOC中的欄位會進行一些計算操作,具體計算規則根據業務而定的。

這些操作都很依賴於業務方,變化之多,很難把控。所以這塊在設計上需要很靈活。

根據抽取出的這兩部分特性,把不變的通用性較強的那部分定義為資料清理,用一個單獨服務處理,這裡採用spark stream流去實時做資料清洗,處理完成之後輸出到kafka佇列。

靈活變化的部分用一個單獨服務處理,業務變更採用指令碼方式動態釋出,修改靈活、即時生效。

第五層,資料儲存層。故名思義就是做一個儲存,前面已經計算好了一個完整的DOC資料。整個計算過程已經耗費了計算資源和時間,所以必須儲存起來。一旦資料應用層服務資料異常,可以很及時用這裡的資料做恢復。

不需要計算,直接拿過去用,恢復起來成本夠低了吧。

有了儲存層,既可以保證下游服務可以完全無狀態,還可以保證快速恢復,同時還可以用作全量資料。龍su簡直是個設計天才,前途無量啊....

一邊寫到儲存層,也會一邊寫到kafka佇列,資料應用層需要獲取kakka佇列資料做增量索引。

整個分層的設計架構就是這樣了,中間的業務細節就不一一講解了。

懂搜尋的朋友肯定會說了,這裡的整個系統說的都是增量,那全量怎麼更新。

這就到點上了,全量我採用了主動觸發的方式,可以想一想那些場景需要做一次全量。

第一、業務發生了欄位級別的變更,比如增加了一個欄位,或者某個欄位的全部值發生了變化。

第二、第一次接進來的業務,但已經有很大一部分原始資料。

第三、有大批增量丟失,導致無法通過容錯機制恢復,而且不是很確定丟失那些增量。

第四、儲存層有髒資料。

第五、資料應用層有髒資料或者異常了。

兩種方式做全量,一種是需要計算的,通過增量鏈路計算做一份全量。另一種是直接通過hbase全量資料來做全量。

hbase有髒資料的情況下只能重新計算,或者清理髒資料。

架構設計注意點

整體的系統架構主要由我完成,系統開發那可是集結了全組的功力。總共用時一個Q出了第一版,目前線上已經跑了好幾個業務,最高qps能達到100k,截了一個線上執行的7天業務指標圖。

說下一些注意點,希望對大家有用。

設計前

  • 對業務一定要非常熟悉,這樣設計出的系統才能更好的服務業務
  • 多做技術方案調查,只有見的多了你才會思考的多了,思考的多了才會有所見解
  • 多溝通,很多問題自己一個人想著可能很完美,但很可能這時你鑽到思維的牛角尖了,溝通能減少這樣的錯誤

設計中

  • 多畫架構圖,畫出來便於你更多的思考,圖畫更具有渲染和說服力,圖片的表達能力比文字強
  • 細節地方一定要畫流程圖,流程圖畫得好寫程式碼才能輕鬆
  • 多做專案評審會,專案評審就是一個產品迭代,只是還沒做出產品就已經有迭代了
  • 更多的傾聽業務,系統設計是為了解決業務問題,是為業務服務的。你的系統可以不是完美的,但對於業務和使用者一定是價值最大的

開發中

  • 線上系統異常處理要完善
  • 測試要完善,功能測試、效能測試都得做
  • 系統監控一定要完善,這個非常重要,沒有監控和日誌,出了問題就是兩眼一抹黑
  • 專案排期一定要做好,一般專案開發都是多人協同開發,不能影響整體排期
  • 有風險及時暴露,這點很重要,很多人在專案中遇到問題或者風險點不敢暴露出來,害怕暴漏出來大家懷疑自己的能力,老闆會給低績效等。想著自己能很快解決,一般遇到風險都很難自己獨自解決,不然也不會構成風險。暴露出來,大家群策群力,也不會拖延到專案排期。

上線後

  • 及時關注自己的服務監控指標,一般上線前都會經過測試、壓測等,很多人就上線關注一會覺得沒問題,就去慶功去了,別把慶功酒喝錯了味道。業務是實時變化的,你要根據業務變化確定你的觀察時機,正確觀察幾個週期無誤後,才可以確定無誤,以防年終獎沒了。敏感業務都必須灰度很長時間做觀測。
  • 聽取反饋意見,收集反饋意見及時迭代自己的產品。
  • 挖掘潛在業務需求,提前佈局迭代。

總結

龍su是第一次做系統性設計,兩個重要的點給大家說說

第一、想清楚在做,想清楚就是指前期需要花費大量的時間去做系統架構調研、討論,細節構思清楚。我的這個系統設計花在調研、探討、設計上的時間佔據總時間的五分之二。構思和測試的時間是最長的,開發的時間是最短的。前期想的越清楚,開發難度越小。更有甚者,開發到中途發現設計不通,再開始返工。

第二、小步快跑,試錯迭代,借用Pony老師的總結。現在網際網路公司的專案都是要求很快速上線的,所以在開發上我們需要快速出產品,然後再不斷迭代。不能一開始就做一個完美產品,這樣使用者是等不住的。

事實上不存在一開始做出來就是完美的產品,只有手機大量使用者意見,不斷迭代、不斷改進、不斷創新的產品才有可能是好產品。

我是龍su,一個在網際網路大器晚成的帥叔叔,我們下期見。

相關文章