一、背景
表格儲存(原名OTS)是一款阿里自研的NoSQL多租戶分散式資料庫,本文主要會分享在表格儲存中,負載均衡系統如何解決熱點問題。
1、表格儲存架構
下圖是表格儲存系統最基本的一個架構圖:
實際上,表格儲存還有很多其他的模組,這裡我們主要看下和本文內容相關的部分,並且也是最核心的一部分。
從下往上看,表格儲存是基於飛天核心的產品,飛天核心主要提供了分散式共享儲存、分散式鎖服務、通訊元件等基礎功能。
然後上面是表格儲存的引擎部分,主要由worker和master組成,一個叢集中有少量的master和大量的worker,master負責管理worker的狀態,並將partition排程到各個worker上提供對外的服務。
再上層是前端元件,提供統一的http服務,並把這些請求轉發到worker上。
2、負載均衡相關的背景
在表格儲存系統中,我們會對使用者資料按分片鍵進行切分,切分之後的一個分片,我們叫做partition,它是表格儲存系統裡面,排程的基本單元,所有排程都是基於partition的。
partition可以做如下操作:
- move:把partition從一臺機器遷移到另外一臺機器上進行服務。
- split:把一個partition分裂成兩個partition。
- merge:把兩個partition合併成一個partition。
- group:group是隔離partition的主要手段,舉個例子:它一般是先將一批worker加入到指定group中,然後將instance、table或者partition也加入到該group,完成這些操作後,系統會將屬於指定group的instance、table的所有partition和顯示指定group的partition都固定排程在該group的worker上,達到隔離的目的。說簡單一點就是我給一些使用者分配指定的機器,這些機器專門給這些使用者服務。
上述的所有對partition的操作,包括move、split、merge、group,都是秒級別的。
3、熱點問題
在NoSQL多租戶系統中經常遇到的熱點問題,主要分為以下兩類:
1)使用者訪問熱點
使用者訪問熱點又分為合理的突發式訪問熱點,以及不合理的突發式訪問熱點:
- 合理的突發式訪問指的是,使用者的表設計合理,只是業務量突然上漲導致的,比如說大促。
- 不合理的訪問熱點指的是,使用者的表設計不合理,在這個基礎上,業務量上漲導致的熱點。
2)機器熱點
機器的熱點問題指的是,該機器的cpu,網路流量由於某些原因突然變高,該機器資源成為瓶頸,導致的熱點。
通常,熱點問題很難處理,主要有如下原因:
- 定位難:系統中的資訊統計不夠全,導致了出現熱點問題,很難定位,只能靠猜。
- 解決難:即使定位了問題,有可能還很難處理,主要原因是系統中處理熱點的手段不足。
- 人工處理慢:即使能定位,也能解決,但是處理時間太長,嚴重影響服務的可用性。
在表格儲存系統中,對上述幾個難點,我們都有對應的手段來解決。針對資訊不全,定位難的問題,我們系統中有詳細的partition級別統計資訊,並且秒級別的partition move、split、merge、group功能也能很好地處理問題。
最後,我們開發了一套負載均衡系統,它能收集資訊、分析資訊、解決問題,做到熱點問題快速自動化解決,不需要人工參與。
二、負載均衡系統
接下來我們來看看錶格儲存中的負載均衡系統是如何自動化解決問題的。首先介紹負載均衡系統的架構,然後分模組來詳細闡述各個模組的功能。
1、負載均衡架構
下圖是負載均衡系統的架構圖:
它主要包括LBAgent和LBMaster兩個角色,其中LBAgent和worker程式部署在同一臺機器上,它負責收集這臺機器上的所有資訊指標,包括worker程式和其他相關的程式。收集之後,在記憶體中維護近期的資料,同時把資料非同步地寫到外部儲存系統中,在圖中我們叫做MetricStore。
然後往上一層的模組是OpsServer,它是很薄的一層封裝,主要提供了所有命令的http服務。
再往上是LBMaster。LBMaster中的collector模組通過OpsServer實時收集LBAgent的資料,並把近期的資料維護在記憶體中,這個模組我們叫做MetricsTable,它主要提供各種資料聚合和top排序的功能。
線上分析模組(OnlineAnalyzer)會實時分析MetricsTable中的近期資料,來檢測是否有熱點等異常的問題。如果有,則對這些資訊進行進一步分析,來產生相應的解決action,並把這些action交給執行模組(Executor)。執行模組通過OpsServer把相應的action傳送給worker或者master,由worker或者master執行action,最終解決熱點問題。
同時,LBMaster還有一個離線分析模組(OfflineAnalyzer),這個模組主要從外部儲存系統MetricStore中讀取資訊,並對這些資訊進行分析,以檢測系統中是否有潛在問題,如果有,則對這些問題產生相對應的action,同樣通過OpsServer交給worker或者master來執行,最終解決潛在的問題,做到防患於未然。
無論是線上分析模組還是離線分析模組,分析出的結果和action都會寫入到一個外部儲存系統中,這裡叫做ResultDataStore,主要為了人工或者系統對這些action做進一步的分析。
最後,LBMaster還提供一個白屏化的管控平臺,這個管控平臺能夠實時查詢LBMaster中的各種資料,同時也可以通過它來傳送人工運維命令。
2、資訊收集模組
資訊收集模組有兩個重點:
- 資訊儘可能地全。
- 不能影響主路徑的效能。
在表格儲存系統中,任何一個模組處理請求時,都會順便收集該模組的相關資訊,這些資訊會隨著請求一起流動。如下圖:
在圖中,經過rpc模組,就會收集rpc模組中的統計資訊;經過m1、m2模組時,也會一起收集m1、m2模組的資訊;最終在返回使用者前,非同步地把資訊推送到一個後臺計算模組,這個模組會在後臺用很少量的資源來彙總這些資訊,並定期把資訊推送給LBAgent。
由於這個後臺計算模組,不在主路徑上執行,是非同步執行的,並且只佔用少量的資源,可能只有一個核的cpu,所以對主路徑的效能影響極小。
通過這種方式,我們既保證了能收集到各個模組的資訊,同時儘可能地減少了對主路徑效能的影響。
3、LBAgent模組
LBAgent模組主要有三個功能:
- 收集單機上的所有資訊。
- 對這些資訊進行預聚合。
- 非同步地持久化所有資訊。
如圖所示:
LBAgent端的接收資訊模組不僅會收到worker程式的資訊,還會收到系統中其他相關程式的資訊。收到資訊之後,LBAgent在記憶體中維護近期收集的資訊,同時非同步地將資訊持久化到外部儲存系統(MetricStore)中,以儲存更長時間。LBMaster通過介面週期性地獲取LBAgent記憶體中維護的資訊。
4、LBMaster模組
LBMater模組是負載均衡系統最核心的模組。它的主要功能是:
- 收集叢集所有資訊。
- 多維度資訊的top查詢,包括但不限於錯誤率、延時、qps等資訊。
- 分析資訊、產生action、執⾏action。
- 自我反饋策略的有效性。
我們結合下圖來看:
collector負責收集資訊,MetricsTable負責多維度資訊的top查詢,OnlineAnalyzer和OfflineAnalyzer模組分別分析線上實時資訊和離線資訊,ActionExecutor模組負責執行分析模組產出的action。
在action執行完成之後,ActionEvaluation模組會比較action執行前後的資訊變化來判斷這個action的效果,通過這種方式來反饋該action是否真正解決了問題。
此外,LBMaster還有一個配置相關的模組,各個模組都有靈活的配置,配置儲存在外部儲存系統中,配置模組會讀取這些資訊,然後同步給所有模組。所有模組的配置都支援實時地動態更新。
最後總結下,LBMaster的有如下特點:
- 冷熱資料儲存分離:其中熱資料儲存在記憶體中,保留最近小時級別的資料,冷資料儲存在外部儲存系統中,可以按需保留數月甚至幾年。
- 離線線上模組分離:從架構圖中可以看到,離線模組和線上模組的路徑不會相互影響。
- 配置靈活、動態載入:LBMaster支援靈活的配置,並且能夠不升級動態載入。
- 白屏化操作及資訊展示:LBMaster中的所有資訊都支援白屏化的展示,並且還可以白屏化傳送運維命令給LBMaster,LBMaster會執行這些運維命令。
- 高可用:由於LBMaster在整個負載均衡系統中起著核心的作用,所以它還要做到高可用。
接下來,我們從線上和離線兩方面來看下負載均衡處理問題的情況。
5、線上分析路徑
首先看線上分析路徑。線上分析主要是分析短期資訊,發現問題,最終解決問題,它主要有如下特點:
- 資料實時性要求極高,分析頻率高,秒級別發現並處理問題。
- 資料量小、全部維護在記憶體表中。
- 主路徑不依賴任何外部系統。
我們從架構圖來看線上分析路徑,可以發現:
- 整個資料流路徑,從worker到LBAgent最後到LBMaster,以及控制流路徑從LBMaster到worker、master,除了分析的結果會非同步地寫外部儲存系統外,不涉及任何外部系統。
- 並且分析結果寫外部儲存系統的失敗也不影響主路徑的執行,它是一個非同步的操作。所有這些設計都是為了滿足實時性的要求。
在表格儲存系統中有很多在分析的策略,下面舉兩個例子:
例1:熱點問題導致讀寫佇列滿報錯
- 首先,負載均衡系統分析資訊會發現worker1的佇列被打滿,報錯,到達了單partition的服務瓶頸。
- 然後進一步分析發現可以做split來解決這個問題,因此負載均衡系統發出split partition1的action,action通過worker和master執行後,partition1被切分為partition11和partition12,並排程到兩臺機器上服務。通過這種方式解決了熱點問題。
例2:機器資源滿導致的問題
負載均衡系統分析資訊發現worker1的資源被打滿,然後開始分析原因,最後發現是partition2導致的,進一步分析發現partition2的訪問模式有問題。
比如說是單partitionkey的訪問,或者順序寫訪問,這種訪問模式,split不能解決問題,所以負載均衡系統發出隔離partition2的action,action執行後,partition2被單獨隔離到一臺機器上服務。
此時,partition2不影響其他任何使用者,並且也獨享整體機器的資源,系統給它提供了最大的服務能力。
6、離線分析路徑
與線上分析路徑恰好相反的是,離線分析主要是分析長期資訊,發現潛在的問題,並最終消除這些潛在問題,做到防患於未然。和線上路徑相比,它的特點是:
- 資料實時性要求低,分析頻率低,小時級別發現並處理問題。
- 由於資料量大,資訊維護在外部儲存系統中。
- 計算量大,所以分析的時候可以依賴外部分析系統。
從架構圖來看,離線分析路徑的資料來源於外部儲存系統,並且由於分析的資料量很大,它會先借助外部分析系統做初步的分析,然後把分析結果寫入到一張結果表中。
最後LBMaster的離線分析模組,對結果表中的資訊做進一步的分析,然後發現問題,產生action。藉助外部分析系統,大大減少了LBMaster的資源消耗,也大大增加了分析的能力。
接下來簡單介紹兩個離線分析策略的例子:
首先是auto merge,在NoSQL系統中,有部分的partition剛開始訪問量很大,所以被切分成很多partition,隨後這些partition的訪問量可能會很低,甚至幾乎沒有,那麼我們就可以將這些partition進行merge,來節約系統資源。
但是,不能通過短期統計資料判斷一個partition訪問量低就對它做merge,因為有些partition的訪問模式是週期性的,所以要通過長期統計資料來判斷一個partition能否做merge。
另外一個例子是,我們可以通過對長期資料的分析來預測某些使用者的訪問峰值,提前做好資源的調整。
7、效果展示
接下來,展示一些負載均衡系統上線後的效果。選取的都是有明顯熱點的業務,所以效果都非常明顯。
如下圖所示,負載均衡系統上線後,讀操作的錯誤率和延時明顯降低,吞吐量明顯提高:
如下圖所示,負載均衡系統上線後,寫操作的錯誤率明顯降低,並且在發現熱點的時候,即錯誤率突然升高時,能立刻處理掉:
三、總結
最後從我自己做負載均衡系統的實踐中總結了幾點經驗:
每個模組的資訊統計是根本
如果沒有資訊統計,或者資訊統計不全,都會導致問題定位不出來或是定位錯誤,整個負載均衡系統都無從談起。並且這部分的工作量絕對不小,不是很簡單就能做到資訊全,並且也幾乎不影響效能的。
把人工處理自動化是最高效的策略
很多人剛開始都會覺得負載均衡要用到非常多的機器學習演算法,這個可能是對的。
但是對於前期來說,我們把人工處理方式來進行自動化處理,可能就能解決90%以上的線上問題,並不需要高大上的機器學習演算法。在經過這個階段之後,一些難點問題,或者預測性的策略方面,再去考慮機器學習的東西。
策略配置豐富,控制靈活
每個策略都要有一些閾值或者條件,這些條件都不能寫死在系統中,都要由配置的方式來傳入,因為線上的情況差異非常大,只有這樣才能有機會針對不同的業務、不同的場景進行配置定製。
系統快速迭代,支援差異化配置
負載均衡系統是一個要求快速迭代的系統,比如今天發現線上一類問題,就需要儘快寫出策略上線,來解決線上的問題。
再者,由於每個業務的特點不同,訪問模式的差異非常大,對可用性的要求也會有很大區別。
所以這裡就需要非常靈活的配置,對於不同的業務,也許是同一個策略都會需要不同的配置才能達對這個業務而言的最優效果。
Q & A
Q1:請問表的統計資訊都統計些什麼?既然有工作者佇列,為什麼還需要擔心處理熱點問題?
A1:在系統中,有部分佇列不是獨享的,可能是整個程式所有partition都共享的,如果一個partition出現了熱點訪問,佔用了所有的資源,可能會導致這臺機器上所有partition的訪問都受到影響。
Q2:那麼不採用hash環的分散式策略,比起明確分割槽鍵值有什麼壞處?為什麼要選用後者?
A2:hash分片最大的問題是,一旦確定之後動態調整比較困難,基於分片鍵的方式,能比較容易做到動態調整,比如split。而hash分片,如果剛開始分片有問題,後續再調整就比較困難。
Q3:我們這邊用的是RabbitMQ,沒有想過要另找一套的思路。當時自己建立這個的時候有沒有參考別的解決方案?然後如何抉擇的?
A3:你這裡的佇列服務可能和我說的不太一樣。如果你們是基於佇列服務做得系統,那麼佇列服務相關的負載均衡你們基本上就無能為力,要看佇列服務這個產品來做,如果你們自己的系統本身也有熱點問題,那麼本次分享應該對你有所幫助。
歡迎工作一到五年的Java工程師朋友們加入Java程式設計師開發: 721575865
群內提供免費的Java架構學習資料(裡面有高可用、高併發、高效能及分散式、Jvm效能調優、Spring原始碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!