時間回到2011年,hadoop作為新生事物,在阿裡巴巴已經玩得風生水起,上千台規模的"雲梯"是當時國内名聲顯赫的計算平台。
這一年,hadoop的好兄弟hbase由畢玄大師帶入淘寶,開啟了它的阿裡之旅。從最初的淘寶曆史交易記錄,到去年的支付寶消費記錄存儲線上曆史存儲統一;從螞蟻安全風控的多年存儲演進,到hbase、tt、galaxy的大資料激情疊代;hbase在阿裡經曆過年輕的苦澀,釋放過青春的活力,也付出過成長的代價。幾代人的不懈努力下,五年陳的hbase開始表現出更成熟、更完善、更豐富的一面,成為公司内部被廣泛使用的存儲産品之一。
本篇會系統性的闡述hbase的定位、建設思路,其中相關内容可能并未深入展開,後續會有專項介紹,請大家随時關注雲栖社群相關文章。
hbase是一個開源的非關系型分布式資料庫(nosql),基于谷歌的bigtable模組化,是一個高可靠性、高性能、高伸縮的分布式存儲系統,使用hbase技術可在廉價pc server上搭建起大規模結構化存儲叢集。
hbase最初是以hadoop子項目的形式進行開發建設,直到2010年5月才正式成為apache的頂級項目獨立發展。伴随着網際網路時代資料的澎湃增長,hbase作為基礎存儲系統得到了快速發展與應用,大批知名商業公司(facebook、yahoo、阿裡等)不自主地加入到了hbase生态建設隊伍,成為apache最活躍的社群之一。
hbase的能力特點,可以簡單概括為下表,基于這些能力,其被廣泛應用于海量結構化資料線上通路、大資料實時計算、大對象存儲等領域

阿裡從2011年初開始步入hbase的發展、建設之路,是國内最早應用、研究、發展、回饋的團隊,也誕生了hbase社群在國内的第一位committer,成為hbase在中國發展的積極布道者。過去的幾年時間,阿裡累積向社群回饋了上百個patch, 在諸多核心子產品的功能、穩定性、性能作出積極重大的貢獻,擁有多位committer,成為推動hbase的長遠發展的重要力量之一。
阿裡是一家綜合生态型公司,内部龐大業務矩陣高速發展,在基礎存儲方面,需要更好的功能靈活性、基礎設施适應性、服務穩定性、效率成本。
是以,阿裡hbase團隊發展維護了hbase的内部分支,其基于阿裡巴巴/螞蟻金服的環境和業務需求,對社群hbase進行深度定制與改進,從軟體系統、解決方案、穩定護航、發展支撐等全方位提供一站式大資料基礎存儲服務。
ali-hbase作為阿裡巴巴大廈的基礎存儲設施,全面服務于淘寶、天貓、螞蟻金服、菜鳥、阿裡雲、高德、優酷等各個領域,滿足業務對于大資料分布式存儲的基本需求。
在剛剛過去的2016年雙11,hbase承載通路量達到了上百gb/秒(寫入)與上百gb/秒(讀取),相當于全國人民一秒收發一條短信,在業務記錄、安全風控、實時計算、日志監控、消息聊天等多個場景發揮重要價值。面對如此規模的業務體量,阿裡巴巴團隊對于如何基于hbase打造穩定、高效、易用的存儲服務,形成了一套完善的産品體系與實踐經驗,其整體大圖如下:
總體上,我們以定制的軟體核心為中心,建設品質平台、運維平台、業務平台和資料流設施四大内容,以支援業務對于基礎資料服務的全方位需求。
接下來,本文會圍繞可用性、資料流、性能優化等方面介紹最近的一些具體工作,希望能夠給相關領域的同學帶來一點幫助。
服務持續可用是網際網路系統的顯著特征,但由于實體環境、軟體bug的不确定性,要做到系統的高可用往往不是一件容易的事,尤其是對于有狀态的存儲系統而言。今天,我們統一使用sla(服務等級協定)去衡量一個分布式系統的可用性,比如sla達到99.99%的系統,其全年的不可用時間小于52.6分鐘;99.999%的系統,其全年的不可用時間小于5.25分鐘,達到這個能力的系統一般可以稱之為高可用。
面對斷電、斷網、硬體故障等實體機房的不可靠性,任何一個高可用系統必須通過雙機房,甚至多機房部署的方式進行容災。對于存儲系統,這就要求資料能夠在機房間備援複制,并保證各個機房的資料對上層應用的一緻性。是以,高可用建設是我們過去很長時間的重要工作。
下面的篇幅,将主要介紹阿裡在使用replication過程中的經驗與改進,期望能和在類似場景工作的同學有所共鳴。
由于線上業務的可用性要求,阿裡hbase很早便開始使用replication功能去部署雙機房容災,迎之而來的第一個大問題是資料複制的效率,尤其異地遠距離部署(比如上海與深圳跨城複制)時更加嚴重,表現為資料複制的吞吐小于用戶端寫入主叢集的吞吐,資料不斷積壓,延遲逐漸增大,隻能等待淩晨低峰期逐漸消化。我們對此進行深入分析,着重優化了以下幾點,才得以保障跨城叢集複制也能穩定保持在秒級内。
提升源端發送效率
hbase replication的基本資料複制過程是源端串行讀取hlog的内容,發送到目标端機器,由目标端解析hlog并寫入資料寫。我們發現,因為源端的串行讀取、發送hlog,當叢集寫入吞吐大的時候,會存在嚴重的性能瓶頸,為此,我們重構了這一塊邏輯,将hlog的讀取與發送解耦,并且發送由單線程優化為多線程,使得整體的源端發送能力大幅提升。
提升目标端sink效率
在replication的預設實作中,源端會按照hlog的原始寫入順序進行回放。為了提升目标端的寫入效率,我們将所有待發送的hlog先進行排序,使得同表同region的資料都能合并處理,同時将目标端的資料寫入盡量并行化。
熱點輔助
盡管做了以上兩點後,叢集間的資料複制能力大大增強,但是個别伺服器仍然會由于負載過大,而産生一定的複制延遲。從本質上來說,這是因為hbase的伺服器配置設定了更多的資源服務于來自用戶端的寫入請求,當某個伺服器成為叢集中的寫入熱點并高負載工作時,這個節點的資料複制基本很難再消化龐大的寫吞吐。這是一個曾困擾我們很久的問題,你可以用一些運維的方式去解決。比如開啟更多的線程數,但這并不能總有效。因為服務于用戶端的線程數,要遠遠大于replication的線程數。再比如從熱點伺服器移走region,降低吞吐與負載,但熱點并不保證是恒定的,可能會跳躍在各個伺服器,我們也開發了新的基于曆史監控的負載均衡算法,以盡可能地讓請求均衡。
很多時候,通過運維管理手段能夠控制影響、化解問題,但當你需要維護上百個叢集時,一點一滴的運維要求慢慢堆積成很高的壁壘。是以,我們嘗試改進系統能力,用自動、一勞永逸地方式去解決熱點下的資料複制積壓問題。面對熱點的基本思路是散列,在這個具體場景上,我們打破原先的自生産自推送的設計,利用整個叢集的能力,使得熱點伺服器上積壓的資料(hlog檔案),能夠由叢集中的其他空閑伺服器進行消化。
配置線上調整
配置的線上調整不僅能極大提升運維幸福感,而且對于系統改進可以産生更加靈活的回報。這并不新鮮,但這是一項十分重要的能力,我們在系統改進的道路上也對其特别重視。hbase的replication功能會有很多參數,我們将其全部優化為可線上調整,給日常的服務支撐帶來了很大的價值。
業務多地多單元部署是阿裡技術架構的一項重要特征,這要求基礎存儲具備資料鍊路的靈活流動性。今天,阿裡hbase會在多地部署多叢集,叢集間資料互相流動,以滿足單元化業務的需求。
在支援資料多鍊路的生産應用上,我們總結了以下幾個要點
表級别鍊路
當一個hbase叢集啟用多個資料鍊路後,我們期望自由設定表的資料可以被複制到其中的一個或多個鍊路,使得整個資料的流動更加靈活。為此,我們增加了一種特性,通過設定表的屬性,以決定該表的資料流向哪些鍊路,使得整個資料流動圖可以由業務架構師任意設計,十分靈活。此外,當需要在叢集間熱遷移資料時,它也能帶來十分重大的作用。 整體效果如下,以表為機關資料可以任意流動:
鍊路可視
當資料可以在多個叢集任意流動後,一個很迫切的需求是鍊路拓撲以及複制狀況的可視。為此,我們強化了replication的資訊層,不僅源端保留它到多個目标的鍊路資訊,而且每個目标端也會保留多個源端到它的鍊路資訊,進而我們可以從任意一個叢集繪制整個鍊路拓撲圖。同時,我們極大豐富replication的運作狀況資訊,并将之彙聚到hbase的master節點,由其統一彙總展現,從中我們可以清晰得到資料是否積壓、複制的性能瓶頸、節點間的均衡情況、具體的延遲時間等資訊,其中複制的延遲時間是一個十分關鍵的資訊。 基本資訊如圖
循環複制
在資料多鍊路下,會産生一些循環複制的場景。比如叢集a->b->c->a,這是一個簡單的連結式複制,當資料流過某個叢集時,hbase replication會在資料中添加該叢集id的資訊,以防止同一條資料被多次流經同一個叢集,基于這個設計,即使複制鍊路存在環,資料也不會産生無限循環流動。但是,仍然有一個效率問題不得不提,對于a<->b<->c<->a這樣一個資料鍊路,我們發現用戶端寫入到a叢集的資料,在b叢集和c叢集上會被複制寫入兩次,一次通過a->b鍊路寫入,另一次通過a->c->b鍊路寫入。是以,為了避免這種寫入放大,需要在鍊路部署上防止産生這種環。在過去實踐的一些場景,發現這種環狀鍊路不得不存在,是以系統層面,我們也對replication做了相關優化,以去除這種寫入放大。
鍊路隔離
當源叢集配置了多個資料鍊路後,我們總是期望這些鍊路之間互相隔離,不會因為一個鍊路的積壓影響其他鍊路。在大多數時候,這一切都如預期工作,但當叢集故障時,糟糕的事情發生了,我們發現一個異常鍊路會阻塞全部鍊路的複制恢複,究其原因,是因為在資料複制的恢複期間,很多資源是所有鍊路共享的。是以,這些資源的鍊路解耦成為我們的工作,同時,也好好對資料複制的當機恢複速度進行了優化。
今天,大多數生産系統會使用異步方式去實作叢集間的資料複制,因為這樣效率更高、邏輯更清晰。這意味着,叢集間資料是最終一緻模型,當流量從主切換到備,從備上無法通路完整的資料,因為複制存在滞後,并且當主叢集永久不可恢複,資料也會存在部分丢失。
為了滿足業務場景的強一緻需求,我們采用了兩種方式。
第一種,異步複制下的強一緻切換。雖然備叢集的資料集滞後于主叢集,但是在主叢集網絡健康的情況下,仍然可以保障切換前後資料的強一緻。
其基本過程如下,首先讓主叢集禁止資料寫入,然後等待主叢集的資料全部複制備叢集,切換流量到備叢集。這裡存在兩個依賴,一個是叢集的寫入控制功能(支援禁止來自用戶端的資料寫入),另一個是複制延遲的确定性,雖然資料是異步複制的,但是我們将資料的複制時間點明确化,即該時間點之前寫入的資料已經完全複制到了備叢集。
第二種,資料複制使用同步的方式。即當資料寫入傳回用戶端成功後,能保證資料在主備叢集均已寫入,進而即使主叢集完全不可恢複,資料在備叢集中也能保證完整。
為了滿足類似場景的需求,阿裡hbase研發了同步方式的叢集間資料複制,具體内容可參考下一節。
資料在叢集間的備援複制,給系統的可用性帶來了數量級的提高,但同時也意味着更大的成本開銷,在保證可用性下如何優化成本是一個需要重點思考的問題,阿裡hbase在這方面投入了較大精力的嘗試,具體内容将在接下來的"性能與成本"章節進行介紹。
上文提到,hbase叢集可以使用異步方式的資料複制來建構雙機房容災,當主叢集故障不能提供服務時,就會切換請求到備叢集,保障系統整體高可用。然而,異步複制模式下存在的問題是:在服務切換後,由于主備叢集間的資料并非強一緻,存在部分資料無法通過備叢集擷取或者通路到的内容過舊。也就是說,如果應用對于資料通路具有強一緻要求,現有的異步複制設計,無法在主叢集故障時,仍然保證系統的高可用。
為此,阿裡hbase團隊投入研發叢集同步複制功能,使得主叢集不可用時,備叢集的資料能達到和主叢集完全一緻,業務可以無感覺的切換到備叢集。相比于異步複制,同步複制會帶來的額外的開銷,但整個寫入吞吐/性能的影響,在我們的設計中,做到了盡量的相近。其整體功能點如下:
資料強一緻性保證。資料寫入主備叢集,主叢集不可用後,備叢集可以恢複所有在主叢集寫入成功的資料
高性能。主備叢集hlog寫入采用異步并行的方式寫入,對寫入性能影響微弱
列族級粒度。列族級别的配置,支援同叢集下同個表的不同列簇可以使用不同的複制方式,同步或異步。
同異步複制共存。任何情況下,同步複制表的任何操作不會影響異步表的讀寫。
靈活切換。備叢集不可用,同步複制可以一鍵切換為異步複制,不阻塞主叢集寫入。
關于資料的強一緻,我們進行了如下定義:
傳回應用成功,則一定主備都寫成功
傳回應用錯誤,則未決(主備是否成功不能确定)
資料一旦讀取成功,則主備永遠均可讀,不會出現主讀成功切換至備後讀不到或者備讀得到主讀不到的情況
任何情況下,保證主備叢集的最終一緻性
我們遵從簡單、高效的原則去設計同步複制功能,簡單意味着該功能與原核心邏輯保持最大程度的隔離,能夠快速達到生産穩定性要求,并能很好地降級成異步複制;高效意味着主備必須并行寫,這在錯誤處理上增加了不少的難度。整體實作方案如下:
用戶端向主叢集寫入資料的時候,會并行寫入兩份log,一份是本地hlog檔案,另一份是備叢集的hlog檔案,我們稱之為remotelog.兩者皆成功,才傳回用戶端成功。
remotelog僅在故障切換後,用以回放資料。正常運作時,不做任何使用,備叢集的資料仍然通過現有的異步複制鍊路寫入。同時,可以通過停寫remotelog,把同步複制降級成異步複制。
hbase資料的多版本特性,使得基于hlog的操作回放具有幕等性,是以,在故障切換後,remotelog中的資料回放會存在一定的重複,但不會影響資料正确性。
主備叢集存在active和standby狀态,隻有active狀态的叢集才能接受用戶端的資料寫入
在備叢集切換為active狀态之前,會對remotelog全局上鎖,進而防止用戶端寫入資料到主叢集傳回成功。這也意味着,主備叢集在任何時刻,隻有一個處于active狀态,不會有腦裂發生。
remotelog會定期由主叢集清理,主叢集伺服器的一個hlog檔案對應一個或多個remotelog,是以當主叢集的hlog檔案中的資料被完全複制到備叢集後,相應的remotelog就可以被删除。
其基本結構如圖
在這裡,主備角色是不對等的,我們通過部署進行配置設定。其中,主->備使用同步複制模式,一旦流量切換到備後,備->主使用異步複制模式。
由于主備雙log的并發寫入,使得同步複制的性能能夠與異步複制接近,在實際使用中,我們觀察到用戶端寫入響應時間增加小于10%。最後,我們列舉一些應用同步複制容災的場景,以供大家參考。
基于狀态變更資料的場景。hbase中提供了checkandmutate接口,用以支援條件寫入/更新/删除,其含義是當某一條件達成時,才執行該寫操作。這意味着查詢到的資料必須是強一緻的,不然就會寫入錯誤的資料。比如,對于一筆交易記錄,其狀态隻能從“已付款”變更為“已發貨”,而不能從其他狀态變更為“已發貨”,是以在資料更新時需要做狀态的條件判斷。
日志/消息的順序訂閱。對于日志/消息産品而言,訂閱資料的完整性是其最核心的保證,也就是說通過hbase進行scan的時候,必須保證能掃描到範圍内的每一行資料。如果切換後,主備資料存在不一緻,則會出現scan過程中跳過某些資料,造成訂閱少資料。
流計算。由于流計算不停地基于中間結果和新的資料流進行疊代處理,作為存儲中間結果的資料庫,必須時刻具備資料的強一緻,才能保證資料計算結果的正确性。
叢集間的資料複制是hbase用來建構機房容災、提供高可用性的重要武器,阿裡hbase通常使用異步複制方式部署,着重改進其在複制效率、多鍊路、一緻性等方面的能力。同時,也研發了一種高效的同步複制方式,以滿足資料強一緻場景的容災需求。
在大資料的發展背景下,沒有一個系統可以處理所有的場景。是以,打通各個系統之間的資料通道,讓資料在線上存儲、實時分析、離線計算中高速流動,形成閉環,是打造大資料平台、挖掘資料價值的關鍵一環。
hbase作為一款高吞吐的線上資料存儲系統,我們希望其能高效、準确地吐出資料,以滿足業務對資料計算分析的多元化需求,這是我們建設hexporter系統的出發點。
hbase業務的資料規模飛速增長,單個業務資料量達到10t,百t級别非常常見,且越來越多的業務要求同步資料到離線計算系統進行計算。同時大部分離線計算任務是周期型,比如按天為機關進行計算,是以資料要按時間分區進行同步并保證單調性,這需要一個高效的時間分區增量方式的資料導出方案來應對日益增長的需求。這是我們建設hexporter系統的場景。
基于以上出發點和場景,我們期望建設一個實時的、高效的hbase資料管道設施,使得寫入到hbase系統的資料可以友善地傳輸複制到其他異構系統,
讓資料因為流動、計算、加工而産生新的價值。為此,阿裡hbase團隊投入研發hexporter系統,其整體上具備以下能力:
實時性。資料可以秒級複制到其他異構系統
準确性。保證資料在hbase與其他系統間的最終一緻性
高吞吐。支援調整緩沖等級和壓縮等級,進而協調資料生産端和資料消費端的能力,達到最大的吞吐量。在實際應用中,hexporter可以有效使用95%的網絡帶寬并保持穩定運作。
容災性。hbase主備容災模式下,資料能夠正常傳輸。
時間确定性。明确标注同步時刻,該時刻之前寫入的資料都已經傳輸完成。基于此,保證計算系統對某個時間分區的完整資料進行計算。
可降級。支援按表取消資料傳輸。
監控告警。支援傳輸延遲的監控與告警。
hexporter系統的整體架構如下:
hexporter的資料是由hbase系統“推送”過來的,其利用了hbase系統本身的内部資料複制機制,模拟了備庫的角色。hbase的regionserver将自身的資料打包,随機發送到hexporter的采集節點。每一個資料包随機的選擇采集節點,是以采集節點之間是完全對等的,可以動态的增加節點來提高hexporter的接收能力,它是水準可擴充的。為了支援主備模式下的hbase,hexporter需要同時采集主備叢集,保證用戶端寫入hbase的資料不會因為主備間的網絡中斷而延遲采集。此時需要解決資料去重的問題:hexporter在收到資料包時,會檢查資料包的标記,這個标記表示了資料是否來自于最源端(用戶端寫入的叢集),如果不是則直接抛棄這個資料包。
大部分離線計算任務是周期型,比如按天為機關進行計算,資料要按時間分區進行同步,是以消費資料時必須能夠擷取時間資訊。hexporter提供兩個次元的時間供消費方使用:業務時間(資料的生成時間)和存儲時間(資料寫入hbase的時間)。
同步時間點指的是一個時刻,在該時刻之前寫入hbase的資料都已經被hexporter采集。由于資料的推送是随機的,是以到達采集節點的資料在時間上是亂序的,同步時間點利用hbase在zookeeper上記錄的日志資訊計算每個regionserver的同步時間點,最後選擇所有regionserver同步時間點中的最小值記為叢集的同步時間點。由于同步時間點的計算是保障資料有序的關鍵,必須能夠容忍當機等問題。在hexporter的設計中,每一個采集節點都可以計算同步時間點,所有節點競争同一個鎖(依賴zookeeper實作),進而獲得這一輪計算同步時間點的權利。隻要有一個采集節點存活,同步時間點的計算就可以正常工作。
目前,hexporter作為阿裡hbase系統的基礎資料傳輸管道設施,每天有上百tb的資料被傳輸到離線計算平台、線上分析引擎、搜尋引擎等系統,這些系統協力配合滿足應用豐富多樣的資料需求。
前面章節提到,我們使用資料在叢集間的備援複制來提高系統可用性,對于主備容災,這意味着我們需要花費一倍的額外成本來換取高可用,能不能降低開銷成為高可用能力是否可以普及的重要門檻。
hbase使用hdfs作為其檔案存儲系統,底層資料存儲預設使用三副本備援以保障資料的可靠性,這也意味着hbase内部的hlog、flush、compaction過程會産生三份資料流量和存儲空間,包括網絡和磁盤。如果hbase的底層副本數能夠從3降低為2,很大程度上可以減少近1/3的成本,但是2個副本在實際運作中的資料丢失率仍然是不小的。是以,對于資料可靠性有要求的環境,三副本是最基本的要求。但是,當我們部署主備容災後,全局擁有了六個副本,能否降低單個叢集的副本為兩個,全局從六個副本降低成四個副本,這成為資源優化的重要入口。
為了容忍單叢集在兩副本下的資料丢失,我們需要建立跨叢集的分區資料複制機制,使得當某一個叢集資料檔案丢失時,可以快速地從另一個叢集進行恢複。為了适用于更多的場景,比如叢集遷移、一鍵建站,我們在設計上會更加通用,支援将某個表的指定範圍資料高效、準确地複制到指定叢集,整體功能可以概括如下:
簡單。可以通過一個接口或者指令執行複制,并在系統ui上實時顯示進度。
快速。整個複制任務會進行拆分,并由不同節點完成,大大提高速度。
容錯和災難恢複。複制過程中任何出錯和當機都能自我恢複。
在實作上,其類似于分布式任務排程,每一個送出的複制作業,會按照rowkey範圍拆成多個子任務,并且子任務的起止範圍是region的子集,由master派發給叢集中的伺服器,并保證失敗後的重新派發。任務排程中的相關資料,統一存儲在zookeeper上,進而保證當機情況下作業的可恢複性。資料的具體複制根據情況會采用完全拷貝和部分複制兩種方式,如果檔案内容的rowkey範圍是子任務的子集,則将其完全拷貝到指定叢集;不然,則使用部分複制的方式,在拷貝期間過濾掉無效的資料。
詳細系統架構如下:
圖中的部分角色說明:
datamigrationmanager: dmm,運作于hbase master,負責接收複制作業、切割作業為多個子任務、派發子任務、監聽完成情況等。
datamigrationworker: dmw, 運作于hbase regionserver,負責完成子任務的資料複制到指定叢集。
job: 一次資料複制作業,由使用者送出,内容包括表名,rowkey範圍以及指定目标叢集的位址資訊。
task: job分割後的子任務,多個子任務的rowkey範圍拼接後組成完整的複制作業的key範圍。
在擁有跨叢集分區資料複制能力後,雙叢集雙副本的運作方式得以應用普及,這能有效降低容災成本。
同時,我們的叢集遷移、表遷移能力大大增強,在不限流下單節點可以達到70mb/秒,更重要的是這變成了一項能力、一個接口服務,而不是一堆運維操作,大大提升運維效率。
對于通常的雙叢集容災部署,同一時間隻有單個叢集提供服務,使得另一個叢集在大部分時間内處于資源閑置。為了改善這一情況,阿裡hbase使用了以下幾種方式:
業務對于資料無強一緻要求,同個業務的部分用戶端通路主叢集,部分用戶端通路備叢集。這種方式對于業務應用部署存在一定的負擔,使其資料庫位址管理複雜化。
交叉部署通路,支援資料的強一緻要求。一般我們會把類似場景的多個業務部署在同個叢集中,通過交叉部署,在同一時間,使得一些業務通路主叢集,另一些業務通路備叢集,進而同時發揮兩個叢集的資源。
用戶端支援同時通路雙叢集。我們通過改造hbase的用戶端,使其支援同時通路雙叢集,這不僅可以提升叢集的資源使用率,還大大降低了通路毛刺,因為任何超過一定時間的請求都會被重發到另一個叢集。
我們經常使用上述一二的方式去優化雙叢集容災下的資源使用,并且取得很不錯的效果。
現階段,由于業務場景對請求穩定性的更高要求,我們開發了“用戶端支援同時通路雙叢集”的功能,以規避單節點抖動(如網絡、磁盤、gc、鎖競争、熱點)的影響,減少應用通路hbase的響應毛刺。從實際測試使用看,開啟該功能後,整體毛刺比例下降達到一個數量級以上,有效去除hbase請求服務時間不穩定的影響。
在過去的幾年,阿裡hbase投入了很大的精力去進行系統的性能優化,包括region級二級索引、bucket cache、small scan、reversed scan等很多重要優化已經回報給社群,并在開源夥伴的一起努力下,不斷更新疊代,讀者可以從社群了解具體的原理與實作。
剛剛過去的2016年雙11,可以說是hbase的一場聖戰,面對巨大峰值流量從容應戰的背後是我們在性能優化上的很多新型武器。
異步api
一直以來,hbase隻能使用同步api方式通路服務,使得吞吐型場景應用端大量線程阻塞在hbase接口,嚴重影響性能,而異步的思想并不陌生。
在去年雙11後,阿裡hbase開發實作了一套全新的異步api,使得用戶端不需要阻塞等待到服務端傳回結果,通過回調函數執行請求成功或失敗後的業務邏輯,大大提升請求吞吐。我們将其應用于監控、安全、日志等場景,整體寫入吞吐可以提升1至3倍。
字首bloomfilter
hbase利用bloomfilter過濾不必要的檔案來提高hbase資料讀的性能,其效果隻支援get不支援scan;在實際使用場景中,有很多業務scan操作會掃描具有相同字首的行,比如物流詳情場景,其rowkey結構是:物流單号+時間戳,一個物流商品會經曆多個狀态,每有一次狀态轉移需要寫入一行資料,這些狀态正常在10個左右,通過scan的方式可以查詢一個物流單号下的所有狀态。針對這個場景我們設計了字首bloomfilter,在業務scan的起止範圍存在公共字首下,使得scan操作也可以使用bloomfilter來過濾檔案,大大提升了查詢效率;菜鳥物流詳情開啟字首bloomfilter後,查詢性能提升一倍,做到大促不擴容,輕松hold住今年大促6.57億包裹的物流詳情查詢。
hlog壓縮
hlog從0.92版本開始支援字典壓縮,但其與replication複制沖突,使得其一直無法真正地被使用,而大量線上業務使用寬表結構,幾十個字段的場景比比皆是,hlog的壓縮将有效提升寫入能力。為此,阿裡hbase重構了hlog的壓縮機制,與hbase replication功能完美相容運作,在消費記錄、資料總線、庫存對賬等多個業務線獲得良好效果,提升寫入20%。
内置計算
資料的聚合、校正、清洗是資料庫系統常見的計算場景,通過外部用戶端進行資料的掃描、計算、更新是我們常用的傳統方式。當面對tb級以上規模的時候,這種方式不僅效率低下,而且對本身的資料服務性能影響巨大。
阿裡hbase一直在探索一種高效、環保的能力去解決我們對于資料基本計算的需求,幾經業務了解與抽象,最終找到一種基于coprocessor的資料庫内置計算方案。它不僅可以提供基本的count、avg、sum、pv、uv等分析聚合能力,也可以提供常見的格式轉換、内容校正、字段清洗等資料管理能力。
其基本原理是,我們在hbase的flush、compaction、查詢傳回等路徑添加coprocessor的hook,并開發很多通用的coprocessor插件,使得hbase服務端能夠在compaction、flush期間就完成資料計算工作,這不僅促使計算結果快速輸出,也大大減少資料存儲io,大大提升整體性能。
2016年,憑借這個能力,多個幾百tb規模業務在一周以内完成字段清洗、格式轉換,并且全程對業務線上通路無影響。憑借這個能力,很多秒級生産的名額資料,應用可以零成本聚合成小時級、日級等粗粒度名額,并對hbase系統減少50%以上的通路壓力。
随着2016天貓雙十一的gmv定格在1207億,hbase的大促目标圓滿完成,然而完美的結果隻是開始,阿裡hbase團隊追求卓越的心永遠不會變,推陳出新也永遠不會停。在未來的日子裡,我們将會重點攻破以下難題。
gc的挑戰
hbase作為java性存儲系統,大容量的記憶體堆使得younggc、fullgc的停頓成為我們一直以來揮之不去的痛苦。探究gc的原理機制,我們明确hbase内部的寫緩沖memstore和讀緩存blockcache是造成gc停頓的最大源頭,正在嘗試用全新研發的完全自管理記憶體的map以替換jdk自帶的map,進而消除gc的影響。
sql
我們正在嘗試提供sql方式通路hbase。它會增加資料類型,降低使用者的開發了解門檻,促進異構系統之間的資料流動效率;它會增加全局二級索引,使得多條件查詢更加高效;它會簡化查詢表達,使得性能優化更加普及;它會增加通用的熱點解決方案,幫助使用者免去複雜的散列邏輯。
容器部署
我們正在嘗試将hbase部署運作于docker之上,使得整體運維更加靈活,叢集伸縮更加自如,資源使用更加充分。