天天看點

如何做到全年配送 0 故障?盒馬揭秘 12個關鍵技術一 、穩定大于一切二、 智能排程鍊路分析三、穩定性因素分析和實踐四、總結

一 、穩定大于一切

盒馬的線下作業穩定性要求極高,假如門店pos無法付款了,排起的支付長隊伍能讓人把門店鬧翻,假如配送員無法攬收了,在家裡預定的午餐材料的饑腸辘辘的客戶能把投訴電話打爆,甚至會形成廣泛的社會輿論。盒馬安全生産至關重要,穩定大于一切。

盒馬配送智能排程負責将訂單指派給騎手,是配送作業實操的第一環節,也是最重要的環節之一,假如排程出現問題,那麼會導緻大量訂單逾時履約,導緻客戶投訴,也會造成客戶取消造成的銷售資損。理論上系統不變更就會降低穩定性的風險,然而随着盒馬配送提效降本的業務訴求和新業務的排程需求,以及配送智能排程上線兩年來更新檔重重導緻的開發運維困難,急需系統架構重構,使得我們必須在高壓下砥砺前行,對系統進行不斷的重構改造,同時支撐日益發展的業務和提效降本的業務訴求。

配送智能排程系統今年系統完全重構一次,遷移了o2o、b2c、冷鍊等重要業務,上線了mall排程新需求,支撐了預排程和實時運力排程的提效降本需求,支撐了算法資料白盒化改造,在此基礎上将繼續耕耘,已産出了政策化營運方案、仿真改造方案和算法結果智能診斷方案,我們用實際行動表明,在系統飛速發展的同時,也能做到了智能排程系統全年0故障。

二、 智能排程鍊路分析

系統穩定性保障前提是要對系統關鍵鍊路了如指掌,關鍵鍊路包括對外依賴和我們提供的服務,是以在接手智能排程系統更新改造時,我們做了非常全面的智能排程的鍊路分析,并在不斷上線新需求後,及時完善鍊路,使得我們不管在大促期間或者日常監控,不管是我們自己運維還是給團隊夥伴運維backup都能了解系統全貌,基于統一鍊路圖進行讨論,并在告警發生時能夠分析和解決問題。

配送O2O智能排程涉及排程系統、壓力系統、基礎資料、騎手平台、算法政策、分布式計算、路徑規劃、單據分發等系統,涉及DTS、diamond、tair、作業DB、降級DB等存儲和中間件,鍊路非常長,我們繪制了一張o2o智能排程時序圖,基于同一張大圖,産品、技術、測試、算法能在大促和系統變更前評估系統穩定性風險。

三、穩定性因素分析和實踐

有了詳細的系統調用鍊路,我們可以把鍊路中的每條線的穩定性按類别進行梳理。

3.1 DB依賴

(1)慢sql

DB依賴主要分析依賴DB的穩定性,首先,DB有沒有慢SQL,盒馬早期大多數故障原因是慢sql導緻,後來對DB的集中治理才使得這塊不穩定因素被逐漸瓦解,但是慢SQL治理是長期的事情,不管是上新業務的sql事前分析,還是流量自然增長需要做的DB定時check都至關重要。

(2)邏輯讀行數多

有些sql不是慢sql,但是邏輯讀非常大,比如超過10萬行,那麼這些sql在業務自然增長時很可能發展為慢sql,如果不治理,假以時日必定讓你“刮目相看”。

(3)CloudDBA中的屬性(cpu、記憶體、load、qps趨勢)

檢視DB的cpu是否正常,load是否比較高水位,是否有很多qps/tps尖刺。配送智能排程依賴的walle庫在大促前發現db整體水位較低,但是cpu尖刺特别高,尖刺有到達60%,而且非常有規律,經過排查是一個網格任務沒有離散導緻。該問題咨詢過DBA如果雙11大促三倍流量,DB扛不住,幸好及時發現,緊急釋出做了網格任務離散化。

(4)DB不隔離

DB不隔離常見有核心與非核心資料在一起,非核心qps高或者邏輯讀高影響了整個DB的穩定性,配送從一個庫拆分為核心、次核心、非核心、歸檔庫,就是為了做到業務重要性分層。

冷熱資料不隔離,一個不經常通路的超慢sql生成的報表使用了核心庫,該case在盒馬發展史上出現多次,常見的有統計報查詢、報表導出使用了核心庫。

讀寫不分離,上述報表類需求、前端展示類需求、看闆類需求屬于讀業務,線下實操核心的是寫DB,兩者不隔離也會同樣産生問題。

(5)DB降級

在智能排程系統中,DB依賴核心作業庫中的單據,核心作業穩定性高于智能排程,為了保障核心作業穩定,我們為DB做了降級政策,用精衛同步一份資料到讀庫。DB降級主要衡量DB不穩定對該DB上業務的影響。

(6)上下遊同一業務字段存在DB字段大小和類型不一緻

上下遊DB使用了同一業務字段但容量不一樣會造成極端場景下資料無法寫入。配送關聯發貨單字段是組合字段,包含批次關聯的所有發貨單,正常情況下一個批次關聯1~3個發貨單,在大促期間倉為了作業友善,關聯了7個發貨單,導緻配送64位字元串超長,導緻關聯發貨單無法寫入,後來緊急變更,将字段改為256位得以解決。商品重量配送的字段是int,表示毫克,某次大促倉庫将一瓶飲料錄入為2噸(商品重量當時無業務應用場景,預留字段),配送子訂單表存儲了多瓶飲料的子訂單,導緻配送無法建立運單。

上下遊同一業務字段要保持一緻,如果有字段轉義,需要做好字段截取、報警、應急預案,在保護好自己的同時,能快速解決異常case。

(7)DB容量、索引等

DBA單表建議小于500萬,不用索引要删除,以免影響寫入性能。

(8)DB變更導緻

改索引、改字段類型、字段擴容會引起鎖表,有的會影響主備同步,假如恰好有業務報表依賴備庫,會造成業務報表不可用。淩晨做的資料結構變更沒有設定停止時間,導緻早上7點DB變更還沒結束,影響了業務。資料變更批量改了gmt_modified時間,恰好有該字段的索引導緻索引重建,影響庫性能,所有依賴精衛都産生延遲。

DB變更要評估變更影響,自己拿不定主意的要找DBA确認,多找老司機咨詢。

(9)db表非utf8mtd

emoji格式文本存儲到非mtd類型表後,查詢導緻emoj無法顯示。

3.2 HSF依賴

(1)hsf服務逾時

hsf逾時時間不能設定太長,特别是高qps和高可用接口,hsf逾時時間過長會導緻hsf線程池打滿,智能排程算法資料采集中,由于qps較高,同時通路ADB容易造成抖動,hsf服務的逾時時間設定預設3秒導緻hsf線程池打滿,資料采集功能在預發環境中排查出不可用。

(2)hsf逾時重試

由于網絡抖動造成的hsf逾時可通過重試避免,相對短的逾時時間+重試機制比預設逾時時間更可靠,在攬單上限hsf服務接口請求時,由于預設3秒逾時和沒有重試導緻每天五百萬服務攬單上限請求有25次左右失敗率,使用了500ms重試+2次重試機制後一周失敗量才1次。

(3)服務緩存

通路資料相對穩定的接口,并且耗時較長的接口需要設定前置緩存,減少通路依賴,同時保證穩定性。強依賴的接口,容易做緩存的接口需要設定後置緩存,當通路服務失敗後能夠請求緩存資料,同時每次請求成功需要更新緩存。

(4)服務降級

強依賴接口當服務不可用時需要設定降級機制,比如降級到上述緩存,或者降級到其他接口,降級到diamond,降級到記憶體等等,保證服務鍊路走通的同時,配合接口報警機制,即時發現依賴服務的問題。

(5)服務隔離

核心應用不能依賴非核心服務,同樣,非核心應用不能依賴核心應用,兩者都會造成核心服務被影響,配送倉配一體化排程和o2o智能排程同時使用walle-grid計算服務,但是一體化排程重要程度低,隻影響排程效果,o2o服務重要程度高影響指派。我們通過版本号對服務進行隔離,如果有需要可根據分組規則或者自定義路由規則進行隔離。

(6)流量預估和壓測

上新功能增加了依賴,或者會有較大新流量的,需要對流量進行預估,并且按流量進行單接口壓測。配送批次組相似度打分服務上預排程功能時,預估增加0.5倍批次,兩兩計算的笛卡爾積是2.25,估計全量開預排程增加3倍以内流量,目前系統在不增加機器情況下可以扛住洪峰,實際開啟預排程後驗證無問題。

3.3 HSF服務提供

(1)服務逾時

相應的服務提供者要提供相對可控的逾時時間,以防被人把線程池打滿,承諾的逾時時間可根據系統壓測後得到,或者通過線上鷹眼的統計給出一個相對靠譜的逾時時間,并不斷優化,預設3秒的逾時在高穩定要求領域盡量少用。

(2)限流

除了設定相對靠譜的逾時時間,還需要對服務能夠提供的流量進行限定,核心服務一定要增加sentinel做限流。sentinel可根據單機限流,粒度可以是qps或者hsf線程數。一般按qps限流較多,微服務也可按線程數限流。

智能排程請求騎手服務,正常情況下騎手服務性能很高,簡單的db的uk查詢,按理說該服務不會有問題,某次大促時db發生了主備切換(DB當時非單執行個體,其他DB影響了),導緻長時間db不可用,高qps流量過來把騎手服務應用線程池打滿,通過限流措施截斷流量,這時上遊排程系統使用後置緩存正常傳回,如果沒有限流,騎手服務導緻線程池被打滿,整體系統将陷入不可用狀況。

(3)幂等

上遊服務重試,下遊保證幂等,幂等包含簡單單據幂等,也有比較複雜的幂等邏輯,比如批量請求的接口。和上遊約定好幂等邏輯,以及幂等傳回值。幂等要傳回成功,服務端自己吃掉異常。

(4)服務緩存

服務提供者通過前置緩存提高系統支撐流量,可應用于傳回值相對穩定的服務,服務緩存是否設定前置緩存可根據緩存命中率評估,有的為了支撐高qps流量但緩存命中率低也可考慮。配送某個打分服務是一個笛卡爾積類型的服務,n個單據就有n*(n-1)/2次調用,假如20秒調用一次,這時候設定1分鐘緩存,理論命中率雖然隻有67%,但提高了2倍流量,可有效減少機器數量。

服務後置緩存通常用來做服務降級邏輯,攬單上限這個核心服務,有三級兜底邏輯,分别是騎手值、城市值、記憶體值,保證服務端的高可用。

(5)服務隔離:同上

(6)流量預估和壓測:同上

3.4 tair依賴

(1)tair各種産品适用場景

MDB是常用的緩存,常用扛高qps,但是MDB不保證持久化,MDB分單叢集和獨立叢集,獨立叢集有兩個叢集資料存儲完全獨立,不能保證資料緩存後能被通路到,MDB不适合用分布式鎖。LDB持久化存儲,非此場景都不需要用。RDB有同步淘汰政策,當容量不夠時會觸發該政策,導緻寫入延遲。批量接口單次請求限制在1024個,建議批量接口單次請求不超過100個。

(2)緩存容量和qps

緩存容量和qps不足時要擴容,MDB一般可支援qps 100萬,RDB10萬。

(3)吞吐量

tair都任何場景都不适合大key和大value的情況,key 1k,value不超過10k,極端情況下會造成資料被拆分,導緻資料丢失,批量寫入要減少批次數,skey不超過5120。

(4)緩存逾時

緩存一定要設定逾時時間,機關是秒,新同學有認為機關毫秒導緻逾時時間過長緩存超容量的情況。

(5)獨立叢集和單叢集

MDB獨立叢集兩個叢集完全獨立,na61隻提供給61機房的系統通路,62通路不到,由于獨立叢集的問題,會導緻緩存資料通路不到。

(6)tair分布式鎖

tair鎖使用put和get方法,鎖的version從2開始,鎖要考慮逾時情況,可通過重試機制避免逾時造成的影響,鎖網絡逾時的ResultCode傳回值可能ResultCode.CONNERROR,ResultCode.TIMEOUT,ResultCode.UNKNOW。

(7)緩存資料一緻性

簡單的一緻性問題比如DB和緩存,db更新成功後可多增加幾個通道保證db執行成功後發出消息,緩存做好幂等,考慮系統挂了的情況可以依賴db變更的精衛消息或者binlog消息做資料對賬。

我們遇到的一緻性問題比較隐蔽,某個打分服務做緩存減少笛卡爾積計算,最開始設定緩存Key是單據,value是相似度分數對象,但是算法在使用單據對象的時候,相似度分數類包含了已配置設定單據對應到站騎手,假如為騎手1,第二次計算的時候,還是拿到的騎手1,但是騎手1已經離站了,導緻一個NP問題,後改成單據+騎手的緩存key才解決該問題。

總結一下,會被上下文修改的對象不适合做緩存,緩存對象要做到粒度小,且不被上下文改變。

(8)緩存擊穿

緩存失效通路DB是一件高風險的事情,特别是高qps情況下,非常容易把DB搞挂,當緩存擊穿之時就是故障來臨之日。設定熱點資料延長過期時間,穩定的資料使用記憶體緩存兜底,使用加鎖政策保護db,db通路限流等。

3.5 Metaq依賴

(1)Metaq consumer線上未注冊

該問題會導緻注冊後批量消息發送。在消息平台中短信業務接入後忘記去線上訂閱導緻訂閱時短信一起發出去,造成業務大大的黑人問号。可以通過低峰期清理topic的消息後,再進行訂閱。

(2)metaq size限制

單條消息限制128k,超過該限制會發送失敗。

(3)metaq 發送失敗

雖然metaq比較穩定,但是偶爾會有metaq發送時失敗的case,可能是metaq broker叢集抖動,網絡問題等,重要的Metaq消息發送要做發送失敗監控,可通過手動補發,或者通過消息對賬,自動重試。

(4)metaq 消費失敗

消費最多重試16次,最大重試間隔2小時,可修改重試間隔減少重試時間,可以設定Metaq循環重試,超過15次後再發送一條metaq,形成metaq循環,不建議死循環,可通過消費時間進行控制。

(5)metaq qps/tps

發送和消費的單topic qps/tps都應小于3000,某次topic tps超過3000被Metaq同學釘釘通知,最後發現是一些廢棄的blink任務在寫,停止後重新開機metaq恢複。

(6)metaq 堆積監控

metaq堆積一般是由于業務系統自身處理失敗引起的,少部分原因是metaq的服務端問題導緻部分通道無法消費,metaq平台可配置消費堆積監控,預設值1萬條,重要業務可設定相對較少的堆積條數,比如設定1000條上限左右。

3.6 精衛依賴

(1)精衛資料傳輸亂碼導緻無法寫入DB json字段

db有個字段是json格式,通過精衛傳輸到讀庫時,由于中文解析問題導緻json格式被破壞,無法寫入db,db字段慎用json格式。

(2)精衛延遲

DB變更,DB索引不一緻,字段不一緻等導緻精衛延遲或者精衛自身問題導緻延遲,重要業務需要配置延遲報警,在DBA和精衛同學雙方确認下,可以加大寫入并發,擴大精衛同步tps,追趕延遲資料。

(3)精衛暫停任務

精衛任務暫停可設定檢測自動重新開機,或者訂閱精衛delay監控,手動重新開機任務。

3.7 DTS依賴

(1)DTS 網格任務/并行任務離散化

并行類任務需要考慮下遊的承載能力做離散化,否則會造成qps熱點。

(2)DTS 降級

可實作一個本地分布式排程任務,在DTS不可用時可降級。

(3)DTS監控

設定DTS逾時監控,DTS傳回失敗監控,DTS沒有正常啟動監控,除了中間件級别的監控以外,還應該設定DTS運作的應用級别調用量監控,在量級穩定的情況下,DTS每分鐘的排程次數應該在門檻值之内。

3.8 開關

(1)開關推送檢查和監控

開關推送要檢查是否生效,推送完開關後要重新整理開關頁面,檢視目前值,最好做一個開關生效日志監控,推送開關後檢視日志是否所有機器都生效。

(2)多個diamond分批釋出開關

多個diamond開關分批釋出要注意,某個開關分批釋出暫停時,其他開關釋出無法生效,需等待其他開關釋出完成。

(3)開關初始化

開關編碼時要注意初始化影響,在系統啟動時,被依賴的開關沒有初始化會有NP風險。

(4)開關多線程影響

我們的開關基本都是單例在多線程環境中使用,開關釋出要注意資料的可見性,比較複雜的數組或map結構,推薦使用影子執行個體完成開關狀态變更。

(5)開關接入changefree

開關變更最好接入changefree,審批人要設定多個,以防緊急開關推送和開關復原找不到聯系人。

3.9 監控

(1)流量監控

流量監控包括提供的服務的qps,依賴服務的qps,周期任務的執行次數等,流量監控反應業務穩定期間的大緻流量。配置監控包括周同比、天環比、流量門檻值。流量監控需要不斷評估和探索業務在合理變化範圍,可用odps統計近一個月的資料,設定相應監控值。

(2)錯誤數量/成功率監控

有些業務流量較低,重要層度卻很高,這時候錯誤數量和成功率監控是最合适的,可以按照分鐘均值來統計,避免網絡原因或系統load抖動造成的正常服務失敗。

(3)錯誤原因監控

錯誤原因監控可快速定位業務錯誤,錯誤日志按照固定格式列印,錯處原因數量按錯誤分類計數。

(4)RT監控

RT是服務時長,反應服務的目前健康度,可按照分鐘均值統計,避免網絡原因或系統load抖動造成的正常服務失敗。

(5)大盤

P級故障具備監控條件的都需要配置在監控大盤,監控大盤能夠總覽所有系統業務監控名額,快速定位具體問題。

(6)系統異常監控

可對所有系統配置NP錯誤監控、資料越界監控、類型轉換錯誤,此類runtime錯誤肯定是系統bug導緻,很可能是釋出導緻的問題,配置該監控能夠第一時間發現釋出的問題。

3.10 灰階

(1)系統對服務有多次狀态依賴不可分布釋出

一個鍊路中兩次依賴系統中的狀态值(db或tair或記憶體或其他存儲),系統正在釋出中,兩次依賴導緻通路了兩個不同的狀态值,狀态不一緻阻塞了系統鍊路。在很多下線作業場景,灰階的粒度是以業務劃分粒度的,而不是以流量,是以某些場景下使用業務單元灰階較合适。

(2)切流前評估流量

在大規模切流前,要評估系統即将承受的流量,在前期切10%左右流量後,能夠近似的根據業務特征對後面90%流量作出合理評估。評估流量後可使用壓測評估機器是否能扛住後續流量。

(3)灰階預期和方案復原

灰階要有業務預期和系統預期,業務預計比如是否按産品流程執行完成,是否灰階流量覆寫了所有TC的case,系統預期比如是否系統error數同比和環比一緻,是否有新增的異常,是否有NP錯誤。

灰階不符合預期需要立即復原,不用考慮任何原因和後果,事後再做分析。預排程灰階期,正好盒馬封網,經過層層審批才上線灰階一個站點,灰階開始10分鐘内業務表現正常,但是系統出現了未曾出現的錯誤日志,随後出現預排程批次不指派,我們立即進行復原。事後分析了一整天(隻在低峰期出現),是緩存對象被改變了導緻NP錯誤。

3.11 測試

(1)預發空跑驗證

預發造測試站點流量,驗證功能可行性,預發空跑是測試驗證前期要完成的,按照TC造多個case,驗證是否符合預期。

(2)預發引流驗證

預發從線上引導流量,驗證産品邏輯,預發從線上引流是為了用大流量驗證系統功能。像智能排程如此長的鍊路,我們用引流可以驗證一些資料難造的場景,以及TC之外的場景

(3)線上引流比對

可單獨為線上站點開起新排程和老排程,并對業務最終指派結果進行比對,從日志上分析行為差異性,是正常的時延差異還是系統bug。還可按照統計學的方法對系統核心名額進行比對分析。

3.12 應急響應

沒有完美設計的系統,bug總是存在,當出現線上問題的時候如何應急處理呢?為了避免線上問題出現時手忙腳亂,需要做好“天晴修屋頂”,這裡的“修”既包含上述架構治理、監控完善,也包含應急預案梳理和故障演練。

(1)應急預案梳理

應急預案包括系統上的開關、限流工具、降級預案等也包含業務測的應急響應措施,在系統短期無法恢複時,也能正常作業下去,比如配送發票作業,能在配送系統無法攬收時,通過發票完成貨物攬收和配送。

系統上的預案要做到事前驗證,在預案上線後驗證預案的有效性;一鍵推送,通過預案平台能夠一鍵觸達,快速生效預案;組織教育訓練,預案要深入人心,讓組内每個同學都掌握如何操作,以及何時操作。

(2)故障演練

為了避免故障來臨時人心慌亂,提高決策效率,縮短問題定位時間,需要在平常做好故障演練。故障演練要當作線上故障對待,由測試在安全生産環境發起,故障演練要做到真實,演練要保密,推薦測試和開發人員使用紅藍對抗實踐故障演練。

為了提高開發應急運維能力,需要有一套故障應對響應機制,盒馬配送從組織、發現、決策、善後四個角度出發,沉澱了一套故障應急響應方法,在故障來臨之際要組織團隊leader和團隊成員停下手頭工作,All In故障處理,首先建立溝通群,其次從大盤監控發現問題點,然後針對問題點決策執行相應預案,當報警恢複時再評估影響面,是否存在故障引起的遺留問題。

(3)故障處理

經過多次故障演練,能有效培養團隊故障發生的應急運維能力,故障發生時切記不要盲目的分析故障原因,而是應以最快速度止血和恢複。80%以上的故障是由變更引起,不管是釋出、開關推送、新增配置、上下遊有釋出等等,少部分是由于流量增長和其他上下文環境變化引起。如果發生故障時存在變更,則需第一時間復原,如果是其他原因,那麼可根據系統症狀,決策推預案、重新開機、擴容等,如果無上述措施,則要分工合作,組織人對外溝通、排查日志、檢查DB、檢視服務流量、分析鍊路trace等,以最快的速度定位問題。

四、總結

智能排程在不停發展中,我們接下來還有政策營運、智能診斷、仿真等進行中的項目,除了已有的穩定性作戰經驗之外,我們還将繼續迎接新的穩定性挑戰,探索不同環境下穩定性最佳實踐。

繼續閱讀