2017年開始阿里HBase走向公有云,咱們有計劃的在逐步將阿里內部的高可用技術提供給外部客戶,目前已經上線了同城主備,將做爲咱們後續高可用能力發展的一個基礎平臺。本文分四個部分回顧阿里HBase在高可用方面的發展:大集羣、MTTF&MTTR、容災、極致體驗,但願能給你們帶來一些共鳴和思考。算法
一個業務一個集羣在初期很簡便,但隨着業務增多會加劇運維負擔,更重要的是沒法有效利用資源。首先每個集羣都要有Zookeeper、Master、NameNode這三種角色,固定的消耗3臺機器。其次有些業務重計算輕存儲,有些業務重存儲輕計算,分離模式沒法削峯填谷。所以從2013年開始阿里HBase就走向了大集羣模式,單集羣節點規模達到700+。緩存
隔離性是大集羣的關鍵難題。保障A業務異常流量不會衝擊到B業務,是很是重要的能力,不然用戶可能拒絕大集羣模式。阿里HBase引入了分組概念「group」,其核心思想爲:共享存儲、隔離計算服務器
如上圖所示,一個集羣內部被劃分紅多個分組,一個分組至少包含一臺服務器,一個服務器同一時間只能屬於一個分組,可是容許服務器在分組之間進行轉移,也就是分組自己是能夠擴容和縮容的。一張表只能部署在一個分組上,能夠轉移表到其它的分組。能夠看到,表T1讀寫通過的RegionServer和表T2讀寫通過的RegionServer是徹底隔離的,所以在CPU、內存上都物理隔離,可是下層使用的HDFS文件系統是共享的,所以多個業務能夠共享一個大的存儲池子,充分提高存儲利用率。開源社區在HBase2.0版本上引入了RegionServerGroup。網絡
壞盤對共享存儲的衝擊:因爲HDFS機制上的特色,每個Block的寫入會隨機選擇3個節點做爲Pipeline,若是某一臺機器出現了壞盤,那麼這個壞盤可能出如今多個Pipeline中,形成單點故障全局抖動。現實場景中就是一塊盤壞,同一時間影響到幾十個客戶給你發信息打電話!特別若是慢盤、壞盤不及時處理,最終可能致使寫入阻塞。阿里HBase目前規模在1萬+臺機器,每週大概有22次磁盤損壞問題。咱們在解決這個問題上作了兩件事,第一是縮短影響時間,對慢盤、壞盤進行監控報警,提供自動化處理平臺。第二是在軟件上規避單點壞盤對系統的影響,在寫HDFS的時候併發的寫三個副本,只要兩個副本成功就算成功,若是第三個副本超時則將其放棄。另外若是系統發現寫WAL異常(副本數少於3)會自動滾動產生一個新的日誌文件(從新選擇pipeline,大機率規避壞點)。最後HDFS自身在高版本也具有識別壞盤和自動剔除的能力。session
客戶端鏈接對Zookeeper的衝擊:客戶端訪問hbase會和Zookeeper創建長鏈接,HBase自身的RegionServer也會和Zookeeper創建長鏈接。大集羣意味着大量業務,大量客戶端的連接,在異常狀況下客戶端的連接過多會影響RegionServer與Zookeeper的心跳,致使宕機。咱們在這裏的應對首先是對單個IP的連接數進行了限制,其次提供了一種分離客戶端與服務端連接的方案 HBASE-20159架構
穩定性是生命線,隨着阿里業務的發展,HBase逐步擴大在線場景的支持,對穩定性的要求是一年更比一年高。衡量系統可靠性的經常使用指標是MTTF(平均失效時間)和MTTR(平均恢復時間)併發
形成系統失效的來源有:
硬件失效,好比壞盤、網卡損壞、機器宕機等
自身缺陷,通常指程序自身的bug或者性能瓶頸
運維故障,因爲不合理的操做致使的故障
服務過載,突發熱點、超大的對象、過濾大量數據的請求
依賴失效,依賴的HDFS、Zookeeper組件出現不可用致使HBase進程退出運維
下面我介紹一下阿里雲HBase在穩定性上遇到的幾個表明性問題:(注:慢盤、壞盤的問題已經在大集羣一節中涉及,這裏再也不重複)異步
在支持菜鳥物流詳情業務的時候,咱們發現機器大概每隔兩個月就會abort一次,由於內存碎片化問題致使Promotion Fail,進而引起FGC。因爲咱們使用的內存規格比較大,因此一次FGC的停頓時間超過了與Zookeeper的心跳,致使ZK session expired,HBase進程自殺。咱們定位問題是因爲BlockCache引發的,因爲編碼壓縮的存在,內存中的block大小是不一致的,緩存的換入換出行爲會逐步的切割內存爲很是小的碎片。咱們開發了BucketCache,很好的解決了內存碎片化的問題,而後進一步發展了SharedBucketCache,使得從BlockCache裏面反序列化出來的對象能夠被共享複用,減小運行時對象的建立,從而完全的解決了FGC的問題。分佈式
HBase依賴倆大外部組件,Zookeeper和HDFS。Zookeeper從架構設計上就是高可用的,HDFS也支持HA的部署模式。當咱們假設一個組件是可靠的,而後基於這個假設去寫代碼,就會產生隱患。由於這個「可靠的」組件會失效,HBase在處理這種異常時很是暴力,當即執行自殺(由於發生了不可能的事情),寄但願於經過Failover來轉移恢復。有時HDFS可能只是暫時的不可用,好比部分Block沒有上報而進入保護模式,短暫的網絡抖動等,若是HBase所以大面積重啓,會把原本10分鐘的影響擴大到小時級別。咱們在這個問題上的方案是優化異常處理,對於能夠規避的問題直接處理掉,對於沒法規避的異常進行重試&等待。
HBase的大查詢,一般指那些帶有Filter的Scan,在RegionServer端讀取和過濾大量的數據塊。若是讀取的數據常常不在緩存,則很容易形成IO過載;若是讀取的數據大多在緩存中,則很容易由於解壓、序列化等操做形成CPU過載;總之當有幾十個這樣的大請求併發的在服務器端執行時,服務器load會迅速飆升,系統響應變慢甚至表現的像卡住了。這裏咱們研發了大請求的監控和限制,當一個請求消耗資源超過必定閾值就會被標記爲大請求,日誌會記錄。一個服務器容許的併發大請求存在上限,若是超過這個上限,後來的大請求就會被限速。若是一個請求在服務器上運行了好久都沒有結束,但客戶端已經判斷超時,那麼系統會主動中斷掉這個大請求。該功能的上線解決了支付寶帳單系統由於熱點查詢而致使的性能抖動問題。
在線上咱們偶爾會遇到某個分區的數量在幾十GB到幾個TB,通常都是因爲分區不合理,而後又在短期內灌入了大量的數據。這種分區不但數據量大,還常常文件數量超級多,當有讀落在這個分區時,必定會是一個大請求,若是不及時分裂成更小的分區就會形成嚴重影響。這個分裂的過程很是慢,HBase只能從1個分區分裂爲2個分區,而且要等待執行一輪Compaction才能進行下一輪分裂。假設分區大小1TB,那麼分裂成小於10GB的128個分區須要分裂7輪,每一輪要執行一次Compaction(讀取1TB數據,寫出1TB數據),並且一個分區的Compaction只能由一臺機器執行,因此第一輪最多隻有2臺機器參與,第二輪4臺,第三輪8臺。。。,而且實際中須要人爲干預balance。整個過程作下來超過10小時,這仍是假設沒有新數據寫入,系統負載正常。面對這個問題咱們設計了「級聯分裂」,能夠不執行Compaction就進入下一次分裂,先快速的把分區拆分完成,而後一把執行Compaction。
前面講的都是點,關於如何解決某個頑疾。致使系統失效的狀況是多種多樣的,特別一次故障中可能交叉着多個問題,排查起來異常困難。現代醫學指出醫院應當更多投入預防而不是治療,增強體檢,鼓勵早就醫。早一步也許就是個感冒,晚一步也許就變成了癌症。這也適用於分佈式系統,由於系統的複雜性和自愈能力,一些小的問題不會當即形成不可用,好比內存泄漏、Compaction積壓、隊列積壓等,但終將在某一刻引起雪崩。應對這種問題,咱們提出了「健康診斷」系統,用來預警那些暫時尚未使系統失效,但明顯超過正常閾值的指標。「健康診斷」系統幫助咱們攔截了大量的異常case,也在不停的演進其診斷智能。
百密終有一疏,系統老是會失效,特別的像宕機這種Case是低機率但必定會發生的事件。咱們要作的是去容忍,下降影響面,加速恢復時間。HBase是一個可自愈的系統,單個節點宕機觸發Failover,由存活的其它節點來接管分區服務,在分區對外服務以前,必須首先經過回放日誌來保證數據讀寫一致性。整個過程主要包括Split Log、Assign Region、Replay Log三個步驟。hbase的計算節點是0冗餘,因此一個節點宕機,其內存中的狀態必須所有回放,這個內存通常能夠認爲在10GB~20GB左右。咱們假設整個集羣的數據回放能力是 R GB/s,單個節點宕機須要恢復 M GB的數據,那麼宕機N個節點就須要 M * N / R 秒,這裏表達的一個信息是:若是R不足夠大,那麼宕機越多,恢復時間越不可控,那麼影響R的因素就相當重要,在Split Log、Assign Region、Replay Log三個過程當中,一般Split Log、Assign Region的擴展性存在問題,核心在於其依賴單點。Split Log是把WAL文件按分區拆分紅小的文件,這個過程當中須要建立大量的新文件,這個工做只能由一臺NameNode來完成,而且其效率也並不高。Assign Region是由HBase Master來管理,一樣是一個單點。阿里HBase在Failover方面的核心優化是採用了全新的MTTR2架構,取消了Split Log這一步驟,在Assign Region上也作了優先Meta分區、Bulk Assign、超時優化等多項優化措施,相比社區的Failover效率提高200%以上
從客戶角度看故障,是2分鐘的流量跌零可怕仍是10分鐘的流量降低5%可怕?我想多是前者。因爲客戶端的線程池資源有限,HBase的單機宕機恢復過程可能形成業務側的流量大跌,由於線程都阻塞在訪問異常機器上了,2%的機器不可用形成業務流量下跌90%是很難接受的。咱們在客戶端開發了一種Fast Fail的機制,能夠主動發現異常服務器,並快速拒絕發往這個服務器的請求,從而釋放線程資源,不影響其它分區服務器的訪問。項目名稱叫作DeadServerDetective
容災是重大事故下的求生機制,好比地震、海嘯等天然災害形成毀滅性打擊,好比軟件變動等形成徹底不可控的恢復時間,好比斷網形成服務癱瘓、恢復時間未知。從現實經驗來看,天然災害在一我的的一輩子中都難遇到,斷網通常是一個年級別的事件,而軟件變動引起的問題多是月級別的。軟件變動是對運維能力、內核能力、測試能力等全方位的考驗,變動過程的操做可能出錯,變動的新版本可能存在未知Bug。另外一個方面爲了避免斷知足業務的需求又須要加速內核迭代,產生更多的變動。
容災的本質是基於隔離的冗餘,要求在資源層面物理隔離、軟件層面版本隔離、運維層面操做隔離等,冗餘的服務之間保持最小的關聯性,在災難發生時至少有一個副本存活。阿里HBase在幾年前開始推動同城主備、異地多活,目前99%的集羣至少有一個備集羣,主備集羣是HBase能夠支持在線業務的一個強保障。主備模式下的兩個核心問題是數據複製和流量切換
選擇什麼樣的複製方式,是同步複製仍是異步複製,是否要保序?主要取決於業務對系統的需求,有些要求強一致,有些要求session一致,有些能夠接受最終一致。佔在HBase的角度上,咱們服務的大量業務在災難場景下是能夠接受最終一致性的(咱們也研發了同步複製機制,但只有極少的場景),所以本文主要專一在異步複製的討論上。很長一段時間咱們採用社區的異步複製機制(HBase Replication),這是HBase內置的同步機制。
同步延遲的根因定位是第一個難題,由於同步鏈路涉及發送方、通道、接受方3個部分,排查起來有難度。咱們加強了同步相關的監控和報警。
熱點容易引起同步延遲是第二個難題。HBase Replication採用推的方式進行復制,讀取WAL日誌而後進行轉發,發送線程和HBase寫入引擎是在同一臺RegionServer的同一個進程裏。當某臺RegionServer寫入熱點時,就須要更多的發送能力,但寫入熱點自己就擠佔了更多的系統資源,寫入和同步資源爭搶。阿里HBase作了兩個方面的優化,第一提升同步性能,減小單位MB同步的資源消耗;第二研發了遠程消耗器,使其它空閒的機器能夠協助熱點機器同步日誌。
資源需求、迭代方式的不匹配是第三個難題。數據複製自己是不須要磁盤IO的,只消耗帶寬和CPU,而HBase對磁盤IO有重要依賴;數據複製的worker本質上是無狀態的,重啓不是問題,能夠斷點續傳,而HBase是有狀態的,必須先轉移分區再重啓,不然會觸發Failover。一個輕量級的同步組件和重量級的存儲引擎強耦合在一塊兒,同步組件的每一次迭代升級必須同時重啓HBase。一個重啓就能夠解決的同步問題,由於同時要重啓hbase而影響線上讀寫。一個擴容CPU或者總帶寬的問題被放大到要擴容hbase總體。
綜上所述,阿里HBase最終將同步組件剝離了出來做爲一個獨立的服務來建設,解決了熱點和耦合的問題,在雲上這一服務叫作BDS Replication。隨着異地多活的發展,集羣之間的數據同步關係開始變得複雜,爲此咱們開發了一個關於拓撲關係和鏈路同步延遲的監控,而且在類環形的拓撲關係中優化了數據的重複發送問題。
BDS Replication
在具有主備集羣的前提下,災難期間須要快速的把業務流量切換到備份集羣。阿里HBase改造了HBase客戶端,流量的切換髮生在客戶端內部,經過高可用的通道將切換命令發送給客戶端,客戶端會關閉舊的連接,打開與備集羣的連接,而後重試請求。
阿里雲同城主備
切換瞬間對Meta服務的衝擊:hbase客戶端首次訪問一個分區前須要請求Meta服務來獲取分區的地址,切換瞬間全部客戶端併發的訪問Meta服務,現實中併發可能在幾十萬甚至更多形成服務過載,請求超時後客戶端又再次重試,形成服務器一直作無用功,切換一直沒法成功。針對這個問題咱們改造了Meta表的緩存機制,極大地提升了Meta表的吞吐能力,能夠應對百萬級別的請求。同時在運維上隔離了Meta分區與數據分區,防止相互影響。
從一鍵切換走向自動切換。一鍵切換仍是要依賴報警系統和人工操做,現實中至少也要分鐘級別才能響應,若是是晚上可能要10分鐘以上。阿里HBase在演進自動切換過程當中有兩個思路,最先是經過增長一個第三方仲裁,實時的給每個系統打健康分數,當系統健康分低於一個閾值,而且其備庫是健康的狀況下,自動執行切換命令。這個仲裁系統仍是比價複雜的,首先其部署上要保持網絡獨立,其次其自身必須是高可靠的,最後健康分的正確性須要保證。仲裁系統的健康判斷是從服務器視角出發的,但從客戶端角度來說,有些時候服務器雖然活着可是已經不正常工做了,可能持續的FGC,也可能出現了持續網絡抖動。因此第二個思路是在客戶端進行自動切換,客戶端經過失敗率或其它規則來斷定可用性,超過必定閾值則執行切換。
在風控和推薦場景下,請求的RT越低,業務在單位時間內能夠應用的規則就越多,分析就越準確。要求存儲引擎高併發、低延遲、低毛刺,要高速且平穩的運行。阿里HBase團隊在內核上研發CCSMAP優化寫入緩存,SharedBucketCache優化讀取緩存,IndexEncoding優化塊內搜索,加上無鎖隊列、協程、ThreadLocal Counter等等技術,再結合阿里JDK團隊的ZGC垃圾回收算法,在線上作到了單集羣P999延遲小於15ms。另外一個角度上,風控和推薦等場景並不要求強一致,其中有一些數據是離線導入的只讀數據,因此只要延遲不大,能夠接受讀取多個副本。若是主備兩個副本之間請求毛刺是獨立事件,那麼理論上同時訪問主備能夠把毛刺率降低一個數量級。咱們基於這一點,利用現有的主備架構,研發了DualService,支持客戶端並行的訪問主備集羣。在通常狀況下,客戶端優先讀取主庫,若是主庫必定時間沒有響應則併發請求到備庫,而後等待最早返回的請求。DualService的應用得到的很是大的成功,業務接近零抖動。
主備模式下還存在一些問題。切換的粒度是集羣級別的,切換過程影響大,不能作分區級別切換是由於主備分區不一致;只能提供最終一致性模型,對於一些業務來說很差寫代碼邏輯;加上其它因素(索引能力,訪問模型)的推進,阿里HBase團隊基於HBase演進了自研的Lindorm引擎,提供一種內置的雙Zone部署模式,其數據複製採用推拉組合的模式,同步效率大大提高;雙Zone之間的分區由GlobalMaster協調,絕大部分時間都是一致的,所以能夠實現分區級別切換;Lindorm提供強一致、Session一致、最終一致等多級一致性協議,方便用戶實現業務邏輯。目前大部分阿里內部業務已經切換到Lindorm引擎。
零抖動是咱們追求的最高境界,但必須認識到致使毛刺的來源能夠說無處不在,解決問題的前提是定位問題,對每個毛刺給出解釋既是用戶的訴求也是能力的體現。阿里HBase開發了全鏈路Trace,從客戶端、網絡、服務器全鏈路監控請求,豐富詳盡的Profiling將請求的路徑、資源訪問、耗時等軌跡進行展現,幫助研發人員快速定位問題。
本文介紹了阿里HBase在高可用上的一些實踐經驗,結尾之處與你們分享一些看可用性建設上的思考,拋磚引玉但願歡迎你們討論。
本文做者: Roin123
本文爲雲棲社區原創內容,未經容許不得轉載。