菜鳥雙11在「倉儲配送資料實時化」的臺前幕後

若有-若無發表於2018-10-29
2017年的雙11,雖然倉配系統做了非常多業務端的優化,使得峰值不會達到如交易系統那般恐怖的程度,但倉配業務鏈路長、節點多、分析維度複雜的業務特點,也使我們在開發倉配實時資料的過程中,面臨了不少挑戰。而正好基於雙11的業務背景,我們也開始著手建立起帶有”倉配特色”的實時資料版圖。
雙11倉配業務系統的預估峰值是日常峰值的n倍以上,我們應該如何保障倉配實時資料如絲般順滑呢?本文將從全域性設計、資料模型、資料計算、資料服務、資料應用、資料保障等各方面作簡單介紹。

一. 全域性設計

實時資料能夠如絲般順滑,離不開各個系統之間的緊密協同。從需求評審的一開始,我們就制定了一套端到端的技術方案。如下圖:
1534927927299-3bc48781-e4bd-4864-8e7a-6b
圖中的內容顯而易見,基於業務系統的資料,資料模型採用中間層的設計理念,建設倉配實時數倉;計算引擎,選擇更易用、效能表現更佳的blink作為主要的計算引擎;資料服務,選擇天工資料服務中介軟體,避免直連資料庫,且基於天工可以做到主備鏈路靈活配置秒級切換;資料應用,圍繞大促全鏈路,從活動計劃、活動備貨、活動直播、活動售後、活動覆盤五個維度,建設倉配大促資料體系。

二. 資料模型

不管是從計算成本,還是從易用性,還是從複用性,還是從一致性……,我們都必須避免煙囪式的開發模式,而是以中間層的方式建設倉配實時數倉。與離線中間層基本一致,我們將實時中間層分為兩層:
第一層是dwd公共明細層,將一些相同粒度的業務系統、維表中的維度屬性全部關聯到一起,增加資料易用性和複用性。能將這麼多的資料來源秒級延遲的情況下產出,也得益於blink強大的狀態管理機制。
第二層是dws公共彙總層,以資料域+業務域的理念建設公共彙總層,與離線有所不同的是,我們根據業務需要,將彙總層分為輕度彙總層和高度彙總層,為了保障資料的時效性,這兩層資料會直接依賴dwd,分別寫到ads和hbase中。
以倉配最重要的“物流訂單/包裹明細表”為例,簡要的資料模型方案設計如下:
1534927968733-30cb8a65-f668-4850-b698-bb
與原來的模型設計方案相比,現在的模型設計方案有如下優勢:
  1. 從lg_order中分流出倉配訂單產出dwd_csn_whc_lgt_first_ord_ri,供下游物流訂單明細、物流包裹明細等實時作業使用,避免從lg_order中直接讀取全量資料,減少不必要的IO;且我們把一些常用的邏輯,如預售標、預約配送標、時效標等全部解析出來,供下游使用。
  1. 重新定位各個業務系統的角色,LC獲取一段訂單資訊,履行獲取計劃資訊,物流寶獲取倉內及物流屬性資訊,tom獲取配送全鏈路資訊,角色分明,同樣的屬性只從一個系統出,如體積屬於物流屬性,以物流寶為準,應簽收時間是計劃資訊,以履行履行為準。這樣,最終將多條實時流join到一起形成最終的明細表,一方面不再像618一樣將履行和實操資料拆分成兩張表,提升資料的易用性;另一方面減少煙囪式的讀取資料,增加資料的複用性。
  2. 彙總層分為輕度彙總層和高度彙總層,輕度彙總層寫入ads,用於前端產品複雜的olap查詢場景,滿足自助分析;高度彙總層寫入hbase,用於前端比較簡單的kv查詢場景,提升查詢效能。

三. 資料計算

今年雙11,我們選擇blink作為主要的實時開發引擎,主要用於產出核心的明細表和部分彙總表;輔以galaxy,主要處理以前遺留的歷史作業。為什麼選擇blink作為今年主要的實時開發引擎呢,基於之前的調研,我們一致認為blink有幾點功能特別具有吸引力:
  1. 強大的blinkSQL功能:雙流join功能,不僅支援兩條資料流join,而且可以在一段程式碼中實現多條資料流join操作;子查詢功能,程式碼中允許使用子查詢,與離線odps基本相同,不需要做任何處理;檢視功能,可以將複雜的SQL語句封裝成檢視,使程式碼更清晰,且資料無需落地成tmp表;維表join功能,支援join hbase維表,且blink為維表join做了諸如 async、cache、multi-join-merge 等優化,使得維表join的效能非常優異……
  2. 強大的流計算效能:blink團隊做了非常多的計算效能優化,諸如MiniBatch優化、維表cache&async、ignore delete、rockDB進行狀態管理以及可以靈活配置資源引數等。經過多次的壓測結果顯示,我們不少明細資料的中間層tps_in能達到非常恐怖的處理速度,這大大超出了我們的預期。
而上面介紹的兩點,還僅僅只是一小部分,基於倉配業務的特點,我覺得我們有必要分享幾個非常驚豔的小功能:
  1. 強大的First&Last:倉配實時資料的大部分資料來自tt,當一條訂單頻繁更新時,會向tt中流入多條訊息,而實際我們需要是最新的一條訊息,如何獲取最新的訊息呢?經過多方打探,我們瞭解到tt是根據tt訂閱時設定的主鍵保序的,首先要保證訂閱的主鍵按照業務需要設定正確,其次我們需要藉助blink提供的強大StringFirst&StringLast函式(StringFirst可以輕鬆獲取第一條訊息的非null資料,而StringLast可以獲取最後一條訊息的非null資料),就可以輕鬆獲取最新的訊息資料。詳細可以參見軍長大神的文章,https://www.atatech.org/articles/94209 
  2. 強大的Retraction機制:剛剛在1中提到,資料庫的同一記錄不斷變化,會往tt中流入多條訊息,如果我們依賴這個tt訂閱直接作一些彙總操作,可能得到的記錄是不對的,舉例來說一筆訂單開始計劃配送公司是中通,後來計劃配送公司變成了圓通,那麼直接針對配送公司進行彙總可能得到的結果是中通和圓通各一筆。如何來處理這種“變key”的場景呢?這需要藉助blink的Retraction機制,需要先使用last函式作特殊處理,然後再做聚合,才能保證最終彙總資料的準確性。詳細可以參見喬燃大神的文章,https://www.atatech.org/articles/94607 
  3. 小而美的nullValues引數:我們都知道,如果源資料某行記錄某個欄位的值是null的時候,從tt流下來的資料,會將null轉化成字串N,這樣對下游使用非常不方便,尤其有用到coalesce等函式的時候,都需要對N進行特別處理,如何能像離線odps一樣”慵懶”的處理這種資料呢?blink在定義inputTable的時候,提供了nullValues引數,比如在訂閱tt inputTable的時候,新增nullValues=`\N|`,blink可以將tt中的N和空字串,全部轉換成null。這樣下游就可以正常使用coalesce等函式時,而不需要對每個欄位中的N和空字串進行特殊處理了。
  4. 高效的狀態管理機制:實時計算過程中(如gby、join等)都會產生大量的state,傳統的流計算引擎基本都是選擇外部儲存(如hbase)作為state儲存方案,blink的選擇是單機效能十分優異的rocksDB,這個方案大大縮短了IO latency,從而獲得倍數的效能提升。結合rocksdb的資料生命週期引數state.backend.rocksdb.ttl.ms,我們可以輕鬆應對倉配物流週期長的業務特點。
在實操中,我們還用到了併發調優、minbatch調整、寫tt使用hashFields保序、特殊場景寫ads ignore delete等不少非常實用的開發和優化技能,這裡就不再一一介紹了,有相關實戰的同學歡迎隨時溝通。

四. 資料服務

因地制宜,在合適的場景選擇合適的資料服務。針對查詢時效要求較高的場景,我們選擇hbase;針對複雜的olap場景,我們選擇ads。在此基礎上,我們使用菜鳥資料部自研的天工作為資料服務中介軟體,一方面遮蔽底層資料庫的差異,另一方面利用天工的邏輯表實現主備鏈路的靈活配置,秒級切換。

五. 資料應用

圍繞大促全鏈路,從活動計劃、活動備貨、活動直播、活動售後、活動覆盤五個維度,建設倉配大促資料體系。基本的資料全鏈路場景如下圖,這裡不再贅述。
1534928017538-98b5806f-a7a9-48b6-a06f-13

六. 資料保障

針對今年雙11的資料保障,我們做了很多事情,這裡只簡單介紹一下倉配實時鏈路的主備方案和資料服務的主備雙活方案。
  1. 實時主備鏈路
對於非常重要的P0P1的實時資料,今年仍然採用實時雙鏈路的保障方案,主鏈備鏈完全獨立,主鏈路全部在et2機房,備鏈路在em14機房,這樣就能做到跨機房容災,當某條鏈路出現問題時,能夠秒級切換到其他鏈路。簡要介紹如下圖:
1534928004342-e15c195d-b5b6-44c9-8870-30
  1. 資料服務主備雙活
今年菜鳥對ads的使用非常多,除倉配業務之外,進口、出口、末端等業務也有部分的實時應用依賴ads。經過分析,我們發現這裡面倉配的實時應用是大頭,如果倉配跟其他業務同時使用主庫,難免不會不對其他業務造成影響。所以,最終我們採取了主備雙活的方案,將倉配一部分頁面的資料切置備庫,保證萬一倉配業務發生故障時,不至於對其他業務造成影響。
  1. 多條實時鏈路壓測
雙11期間,100%的資料可用性,當然離不開實時鏈路壓測的功勞。為了頂住日常50倍峰值的TPS,我們準備了5條實時壓測鏈路,如下:
a. 實時主鏈路
b. 實時備鏈路,為P0/P1級應用而準備
c. 交易壓測鏈路,為配合集團交易鏈路壓測而準備
d. 全鏈路壓測鏈路,為配合集團全鏈路壓測而準備
e. 菜鳥壓測鏈路,菜鳥“特色鏈路”
其中,e鏈路是菜鳥的“特色”鏈路,為什麼這麼說呢?上文中數次提到倉配的業務週期特別長,雙11期間從物流訂單建立到簽收全部簽收可能不止1天,加上倉配上游系統特別多,LC、WLB、TOM、FL又是完全獨立的系統,需要多條實時流的join操作,如果壓測僅用tt中儲存的3天的歷史資料,很難真正壓測出效果,很可能因為週期過短導致最終關聯上的記錄沒有實際的多,所以我們將odps tt4表最近20天的資料導回tt,基於odps離線導回來的最近20天的訊息量進行壓測,這是當前最適合倉配的壓測模式,也是能發現問題最有力的手段之一。

七. 後續展望

雖然雙11已經結束,但是我們有必要覆盤一下過程中遇到的一些遺留問題:
  1. 壓測過程過於複雜,人為的工作太多,後續的壓測鏈路需要實現自動化的全鏈路壓測,也許是一個按鈕、也許是一句口令……就能完成各條鏈路的壓測。
  2. 攬收x小時未簽收等指標,暫時沒有想好更好的實現方案,只能從ads的明細表中獲取,對ads的查詢壓力太大,後續需要調研其他實現方案。
  3. 類似CBO的自適應資源配置,將人的經驗進一步整合,形成自動化的資源配置優化方案,避免大量的人工優化。
  4. 防火防盜防傾斜,針對gby端的資料傾斜,一般的做法是兩次gby處理,第一個gby區域性聚合,第二個gby全域性聚合,後續需要調研是否能像離線odps的skew gby引數一樣,自動去做,而不是認為去寫兩次gby操作。
  5. 離線資料的處理,實時和離線的大統一也許就在某一天。
  6. 天工端做了非常多的邏輯處理,後續可以適當將一些通用的資料服務介面公共化,提升介面複用率。

八. 作者簡介

賈元喬(緣橋),來自菜鳥-CTO-資料部-倉配資料研發,主要負責菜鳥倉配業務的離線和實時資料倉儲建設以及創新資料技術和工具的探索和應用。

1535102091246-989b837d-05a8-4443-838b-c1

如果您有實時報表/實時資料大屏/實時金融風控/實時電商推薦等相關實時化資料處理需求,可以加入如下釘釘交流群!

TB1HzWqB7CWBuNjy0FaXXXUlXXa-157-150.png


相關文章