京东JDHBase异地多活实践
JDHBase在京東集團作為線上kv存儲,承擔了大量在線業務,11.11、6.18 均經歷了每天萬億級讀寫訪問請求,目前規模達到7000+節點,存儲容量達到了90PB。場景涉及商品訂單、評價、用戶畫像、個性推薦、金融風控、物流、監控等700+業務。
?
?
JDHBase上承載了大量核心業務,遍布全球多個Data Center。為了保障業務穩定不間斷運行,我們構建了JDHBase集群的異地多活系統。主要介紹在我們在異地多活系統的實踐。
?
?
HBase Replication原理
?
HBase是典型的LSM(Log-Structured Merge-Tree)結構數據庫,服務端響應客戶端寫請求過程中,會寫入Memstore(內存)中和順序的寫入WAL日志(HDFS文件)中,WAL日志確保數據真正寫入磁盤,從而在節點故障時恢復未被持久化的內存數據。
?
?
HBase的Replication是基于WAL日志文件的。在主集群中的每個RegionServer上,由ReplicationSource線程來負責推送數據,在備集群的RegionServer上由ReplicationSink線程負責接收數據。ReplicationSource不斷讀取WAL日志文件的數據,根據Replication的配置做一些過濾,然后通過replicateWALEntry的rpc調用來發送給備集群的RegionServer,備集群的ReplicationSink線程則負責將收到的數據轉換為put/delete操作,以batch的形式寫入到備集群中。
?
?
因為是后臺線程異步的讀取WAL并復制到備集群,所以這種Replication方式叫做異步Replication,正常情況下備集群收到最新寫入數據的延遲在秒級別。
?
?
JDHBase異地多活架構
?
JDHBase服務端與客戶端交互主要包含三個組件:Client、JDHBase集群、Fox Manager。
Client啟動時首先向Fox Manager端匯報用戶信息,Fox Manager進行用戶認證后,返回集群連接信息,Clinet收到集群連接信息后,創建集群連接HConnection,從而與Fox Manager指定的集群進行數據交互。
?
1、Fox Manager配置中心
負責維護用戶及JDHBase集群信息,為用戶提供配置服務,同時管理員做配置管理。
?
-
Policy Server:分布式無狀態的服務節點,響應外部請求。數據持久化目前為可選的Mysql或Zookeeper。Policy Server中還包含了一個可選的Rule Engine插件,用于根據規則和集群的狀態,自動修改用戶配置,如集群連接地址信息、客戶端參數等。
-
Service Center:Admin配置中心的UI界面,供管理員使用。
-
VIP Load Balance:對外將一組Policy Server提供統一訪問地址并提供負載均衡能力。
2、JDHBase Cluster
JDHBase Cluster提供高吞吐的在線OLTP能力。我們對可靠性要求比較高的業務做了異地多活備份。
?
?
-
Active Cluster:正常情況下業務運行在此集群上。數據會異步備份到Standby Cluster,同時保證數據不丟失,但是會有延遲。
-
Standby Cluster:異常情況下,全部或部分業務會切換到此集群運行。在此集群上運行的業務數據也會異步備份到Active Cluster上。
兩個集群間通過Replication備份數據,根據集群ID防止數據回環。主備集群間數據達到最終一致性。
實際生產中,我們根據兩個建群間的Replication,構建了多集群間的Replication拓撲,使得集群互為主備。一個集群上會承載多個業務,不同的業務的備份也會散落在不同的集群上,形成多集群間的拓撲結構。?
?
3、Client
?
?
Client負責拉取Fox Manager端配置信息,根據配置信息為用戶提供接口,與主集群或者備集群進行數據交互,同時將客戶端狀態上報給Fox Manager端。
?
?
集群切換
?
HBase在讀寫數據時,需要先經過數據路由,找到數據所在(或應當所在)的節點位置,然后與節點進行數據交互。簡單來說包含以下三步:
1、client端訪問HBase集群的zookeeper地址,通過訪問znode獲取集群META表所在位置。
2、訪問META表所在節點,查詢META表獲取數據分片(Region)信息。同時緩存META表數據。
3、根據數據分片信息訪問數據所在節點,進行數據交互。
?
?
JDHBase在client端數據路由前,多加了一步訪問Fox Manager的步驟,這一步驟主要有兩個作用:一是進行用戶認證;二是獲取用戶集群信息;三是獲取客戶端參數。
?
?
對集群切換來說,重要的是用戶集群信息和客戶端參數。Client端拿到具體的集群信息(zk地址),然后進行正常的數據路由,這樣業務的client端不需要關心訪問哪個集群,Fox Manager端只要保證為client提供的路由集群可用即可。
Fox Manager還會為Client提供一些特殊配置參數,例如重試、超時等,這些配置參數依據兩個維度:集群特性和業務屬性。這些參數的設置需要結合業務場景和要求長期觀察,屬于專家經驗;也包括一些極端情況下的臨時參數。
我們也在client sdk中添加了metrics,用于評估client端視角的服務可用性。基于metrics,我們為一些極度敏感的業務開啟客戶端切換,當客戶端可用率降低生效。
在client sdk中添加的metrics,用于評估client端視角的服務可用性。Client啟動后會與Fox Manager建立心跳,一方面通過心跳上報客戶端狀態以及部分metrics指標到Fox Manager,這些數據能夠幫助我們分析服務運行狀態;另一方面Client端能夠獲取Fox Manager端對Client的配置更新。這樣,當管理員在Fox Manager為Client更新了集群配置,Client端能夠及時感知并重建數據路由。
另外,我們也做了對Client的精準控制。一方面可以使業務的部分Client實例路由到不同集群,另一方面可以作為一些極端情況下單個Client實例強制更新集群信息并切換的備用手段。
?
?
自動切換
?
在有了主備集群切換之后,我們仍面臨時效性的問題。故障情況下,我們從監控到異常到報警,到人工介入,最快仍需要分鐘級恢復服務可用性。這對一些線上業務來說仍然不可接受。
為了提高服務SLA質量,我們開發了基于策略的主備集群自動切換。可以根據策略在服務異常時,觸發切換,將故障恢復時間控制到秒級。
?
?
首先我們在HMaster上做了狀態檢測插件,用于收集一些影響服務可用性的指標信息,heartbeat的方式上報到Fox Manager的PolicyServer中。
PolicyServer 是對外提供查詢和修改策略的服務,它所有策略數據會存儲在MySQL中。可以通過加節點的方式動態擴展形成一個服務集群,避免單點問題。
PolicyServer中的Rule Engine負責根據HMaster上報的集群狀態的指標信息推測執行切換策略。服務可用性對不同指標的敏感度不同,本質上Rule Engine在多個時間窗口上對不同的指標或多個指標的組合執行策略。
Rule Engine不需要高吞吐,重要的是保障可用性,因此基于Raft做了高可用。Active的Rule Engine節點掛掉后,立即會被另外一臺節點接管。
?
動態參數&自動調速
?
Replication本身是通過RegionServer發送到備機群,而RegionServer本身有大量線程用于客戶端請求,Replication Source的線程和負載很難與客戶端請求相匹配,在大量寫或者有熱點的情況下,很容易出現Replication積壓。
這個問題我們可以通過調節Replication 參數來緩解這種積壓的情況。HBase本身基于觀察者模式支持動態參數,更新RegionServer節點參數后,執行update config動作即可生效。我們擴展了動態參數,將Replication的一些參數做成了動態生效的。當Replication積壓比較嚴重時,可以在集群上或者在響應的分組、節點調整參數,不需要重啟節點。
雖然Replication動態參數不需要重啟RegionServer,但是上線還是比較麻煩的,需要人工參與,并且寫熱點積壓不可預測,依然很難做到Replication平穩順滑。因此我們進一步在Replication Source端根據當前節點積壓的情況(幾個閾值),在一定范圍內自動調節Replication參數,從而達到自動調速的功能。目前參數自動調節范圍在基礎參數值的1-2倍之間。
跨機房異地數據中心的之間的帶寬是有限的,在業務流量高峰期不能將有限的網絡資源用于同步數據。因此在Fox Manager端我們也做了對集群的相應控制,分時段調整Replication速度。
?
串行Repication
?
主備集群間的Replication本身是異步的,正常情況下兩個集群可以達到最終一致性。但是某些情況下并不能完全保證。
在HBase的Replication中,通過讀取每個RegionServer中的WAL將數據變化推到備集群。HBase在zookeeper中維護了一個對WAL文件的隊列,因此可以按創建時間順序讀取這些WAL文件。但是當Region發生移動或者RegionServer故障轉移,那么Region所在的新的RegionServer上的WAL日志可能會先于老的WAL日志推送到備集群,這種情況下備集群上的數據寫入順序與主集群是不一致的。更極端的情況,如果這種順序不一致發生在同一條數據上,那么可能會導致數據永久不一致。
舉個例子,首先在主集群中執行Put,然后執行Delete來刪除它,但是Delete操作先replication到了備集群,而備集群如果在接收Put之前進行了major compact,major compact過程會刪除掉delete marker,隨后備集群接收到了這條put,那么這條put在備集群上將沒有機會再delete,將會一直存在。
解決這個問題需要保證任何情況下,Replciation的順序與主集群的mutation順序是一致的,即串行Replication(Serial Replication, backport form v2.1)。例如當Region發生移動從RegionServer1移動到了RegionServer2,那么RegionServer2應當等待RegionServer1將此region的所有數據推送完,再進行推送。
串行Replciation使用Barrier和lastPushedSequenceId來解決這個問題。每當Region發生Open時,都會在meta表中記錄一個新的Barrier,這個Barrier為當前Region的最大SequenceId + 1。lastPushedSequenceId為當前region推送到備集群的SequenceId,在Replciation的過程中,每個batch成功,會在Zookeeper中記錄最大的SequenceId,即lastPushedSequenceId。
?
?
如圖所示,一個Region從RegionServer1移動到RegionServer2,又到RegionServer3,發生多次Region Open,記錄了多個Barrier,構成多個Range:[ Barrier(n) , Barrier(n+1) )。期間有多個mutation操作記錄的SequenceId:s1、s2、s3、……
RegionServer在進行數據Replication前,首先檢查lastPushedSequenceId 是否大于自己區間的起始Barrier。例如上圖中RegionServer3會首先檢查,當lastPushedSequenceId >= Barrier1 – 1時才會進行Replication,而此lastPushedSequenceId = s2,則說明lastPushedSequenceId所在Range的RegionServer2正在進行Replication,那么RegionServer3需要等待。這樣就保證了數據抵達備集群的順序與主集群的寫入順序是相同的。
?
總結與展望
?
JDHBase在不斷吸收業界異地災備經驗的同時,也經過一系列的實踐和演進,目前SLA已經能夠達到99.98%,從毫無異地容災措施到完善的監控、告警、切換、一致性保障機制,為業務提供穩定可靠的存儲服務。
同時隨著業務的增多和數據量的增大,集群規模也越來越大,仍面臨一些挑戰,未來我們在異地災備方面將會著力在同步的Replication、去zookeeper依賴、客戶端視角自動切換、降低數據冗余等方面繼續提升可靠性及穩定性。
?
?
References
1、https://hbase.apache.org/book.html#_cluster_replication
2、https://mapr.com/blog/in-depth-look-hbase-architecture/
3、hhttps://issues.apache.org/jira/browse/HBASE-20360
4、https://issues.apache.org/jira/browse/HBASE-20046
總結
以上是生活随笔為你收集整理的京东JDHBase异地多活实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 列一下OOP规约,编程的时候共勉!别踏坑
- 下一篇: 监控指标10K+!携程实时智能检测平台实