HBase 讀流程解析與優(yōu)化的最佳實(shí)踐

一工闺、前言

本文首先對(duì) HBase 做簡(jiǎn)單的介紹效拭,包括其整體架構(gòu)、依賴組件浑度、核心服務(wù)類的相關(guān)解析寇窑。再重點(diǎn)介紹 HBase 讀取數(shù)據(jù)的流程分析,并根據(jù)此流程介紹如何在客戶端以及服務(wù)端優(yōu)化性能俺泣,同時(shí)結(jié)合有贊線上 HBase 集群的實(shí)際應(yīng)用情況疗认,將理論和實(shí)踐結(jié)合,希望能給讀者帶來啟發(fā)伏钠。如文章有紕漏請(qǐng)?jiān)谙旅媪粞院崧覀児餐接懝餐瑢W(xué)習(xí)。

二熟掂、 HBase 簡(jiǎn)介

HBase 是一個(gè)分布式缎浇,可擴(kuò)展,面向列的適合存儲(chǔ)海量數(shù)據(jù)的數(shù)據(jù)庫赴肚,其最主要的功能是解決海量數(shù)據(jù)下的實(shí)時(shí)隨機(jī)讀寫的問題素跺。 通常 HBase 依賴 HDFS 做為底層分布式文件系統(tǒng),本文以此做前提并展開誉券,詳細(xì)介紹 HBase 的架構(gòu)指厌,讀路徑以及優(yōu)化實(shí)踐。

2.1 HBase 關(guān)鍵進(jìn)程

HBase是一個(gè) Master/Slave 架構(gòu)的分布式數(shù)據(jù)庫踊跟,內(nèi)部主要有 Master踩验, RegionServer 兩個(gè)核心服務(wù),依賴 HDFS 做底層存儲(chǔ),依賴 zookeeper 做一致性等協(xié)調(diào)工作箕憾。

  • Master 是一個(gè)輕量級(jí)進(jìn)程牡借,負(fù)責(zé)所有 DDL 操作,負(fù)載均衡袭异, region 信息管理钠龙,并在宕機(jī)恢復(fù)中起主導(dǎo)作用。
  • RegionServer 管理 HRegion御铃,與客戶端點(diǎn)對(duì)點(diǎn)通信碴里,負(fù)責(zé)實(shí)時(shí)數(shù)據(jù)的讀寫,上真。
  • zookeeper 做 HMaster 選舉并闲,關(guān)鍵信息如 meta-region 地址,replication 進(jìn)度谷羞,Regionserver 地址與端口等存儲(chǔ)帝火。

2.2 HBase 架構(gòu)

首先給出架構(gòu)圖如下


圖1 HBase架構(gòu)圖

架構(gòu)淺析: HBase 數(shù)據(jù)存儲(chǔ)基于 LSM 架構(gòu),數(shù)據(jù)先順序?qū)懭?HLog湃缎,默認(rèn)情況下 RegionServer 只有一個(gè) Hlog 實(shí)例犀填,之后再寫入 HRegionMemStore 之中。HRegion 是一張 HBase 表的一塊數(shù)據(jù)連續(xù)的區(qū)域嗓违,數(shù)據(jù)按照 rowkey 字典序排列九巡,RegionServer 管理這些 HRegion 。當(dāng)MemStore達(dá)到閾值時(shí)觸發(fā)flush操作蹂季,刷寫為一個(gè) HFile 文件冕广,眾多 HFile 文件會(huì)周期性進(jìn)行 major, minor compaction 合并成大文件偿洁。所有 HFile 與日志文件都存儲(chǔ)在HDFS之上撒汉。
至此,我們對(duì) HBase 的關(guān)鍵組件和它的角色以及架構(gòu)有了一個(gè)大體的認(rèn)識(shí)涕滋,下面重點(diǎn)介紹下 HBase 的讀路徑睬辐。

三、讀路徑解析

客戶端讀取數(shù)據(jù)有兩種方式宾肺, GetScan溯饵。 Get 是一種隨機(jī)點(diǎn)查的方式,根據(jù) rowkey 返回一行數(shù)據(jù)锨用,也可以在構(gòu)造 Get 對(duì)象的時(shí)候傳入一個(gè) rowkey 列表丰刊,這樣一次 RPC 請(qǐng)求可以返回多條數(shù)據(jù)。Get 對(duì)象可以設(shè)置列與 filter增拥,只獲取特定 rowkey 下的指定列的數(shù)據(jù)啄巧、Scan 是范圍查詢洪橘,通過指定 Scan 對(duì)象的 startRow 與 endRow 來確定一次掃描的數(shù)據(jù)范圍,獲取該區(qū)間的所有數(shù)據(jù)棵帽。
一次由客戶端發(fā)起的完成的讀流程,可以分為兩個(gè)階段渣玲。第一個(gè)階段是客戶端如何將請(qǐng)求發(fā)送到正確的 RegionServer 上逗概,第二階段是 RegionServer 如何處理讀取請(qǐng)求。

3.1 客戶端如何發(fā)送請(qǐng)求到指定的 RegionServer

HRegion 是管理一張表一塊連續(xù)數(shù)據(jù)區(qū)間的組件忘衍,而表是由多個(gè) HRegion 組成逾苫,同時(shí)這些 HRegion 會(huì)在 RegionServer 上提供讀寫服務(wù)。所以客戶端發(fā)送請(qǐng)求到指定的 RegionServer 上就需要知道 HRegion 的元信息枚钓,這些元信息保存在 hbase:meta 這張系統(tǒng)表之內(nèi)铅搓,這張表也在某一個(gè) RegionServer 上提供服務(wù),而這個(gè)信息至關(guān)重要搀捷,是所有客戶端定位 HRegion 的基礎(chǔ)所在星掰,所以這個(gè)映射信息是存儲(chǔ)在 zookeeper 上面。 客戶端獲取 HRegion 元信息流程圖如下
圖2 客戶端尋址圖

我們以單條 rowkey 的 Get 請(qǐng)求為例嫩舟,當(dāng)用戶初始化到 zookeeper 的連接之后氢烘,并發(fā)送一個(gè) Get 請(qǐng)求時(shí),需要先定位這條 rowkey 的 HRegion 地址家厌。如果該地址不在緩存之中播玖,就需要請(qǐng)求 zookeeper (箭頭1),詢問 meta 表的地址饭于。在獲取到 meta 表地址之后去讀取 meta 表的數(shù)據(jù)來根據(jù) rowkey 定位到該 rowkey 屬于的 HRegion 信息和 RegionServer 的地址(箭頭2)蜀踏,緩存該地址并發(fā) Get 請(qǐng)求點(diǎn)對(duì)點(diǎn)發(fā)送到對(duì)應(yīng)的 RegionServer(箭頭3),至此掰吕,客戶端定位發(fā)送請(qǐng)求的流程走通果覆。

3.2 RegionServer 處理讀請(qǐng)求

首先在 RegionServer 端,將 Get 請(qǐng)求當(dāng)做特殊的一次 Scan 請(qǐng)求處理殖熟,其 startRow 和 StopRow 是一樣的随静,所以介紹 Scan 請(qǐng)求的處理就可以明白 Get 請(qǐng)求的處理流程了。

3.2.1 數(shù)據(jù)組織

讓我們回顧一下 HBase 數(shù)據(jù)的組織架構(gòu)吗讶,首先 Table 橫向切割為多個(gè) HRegion 燎猛,按照一個(gè)列族的情況,每一個(gè) HRegion 之中包含一個(gè) MemStore 和多個(gè) HFile 文件照皆, HFile 文件設(shè)計(jì)比較復(fù)雜重绷,這里不詳細(xì)展開,用戶需要知道給定一個(gè) rowkey 可以根據(jù)索引結(jié)合二分查找可以迅速定位到對(duì)應(yīng)的數(shù)據(jù)塊即可膜毁。結(jié)合這些背景信息昭卓,我們可以把一個(gè)Read請(qǐng)求的處理轉(zhuǎn)化下面的問題:如何從一個(gè) MemStore愤钾,多個(gè) HFile 中獲取到用戶需要的正確的數(shù)據(jù)(默認(rèn)情況下是最新版本,非刪除候醒,沒有過期的數(shù)據(jù)能颁。同時(shí)用戶可能會(huì)設(shè)定 filter ,指定返回條數(shù)等過濾條件)
在 RegionServer 內(nèi)部倒淫,會(huì)把讀取可能涉及到的所有組件都初始化為對(duì)應(yīng)的 scanner 對(duì)象伙菊,針對(duì) Region 的讀取,封裝為一個(gè) RegionScanner 對(duì)象敌土,而一個(gè)列族對(duì)應(yīng)一個(gè) Store镜硕,對(duì)應(yīng)封裝為 StoreScanner,在 Store 內(nèi)部返干,MemStore 則封裝為 MemStoreScanner兴枯,每一個(gè) HFile 都會(huì)封裝為 StoreFileScanner 。最后數(shù)據(jù)的查詢就會(huì)落在對(duì) MemStoreScanner 和 StoreFileScanner 上的查詢之上矩欠。
這些 scanner 首先根據(jù) scan 的 TimeRange 和 Rowkey Range 會(huì)過濾掉一些财剖,剩下的 scanner 在 RegionServer 內(nèi)部組成一個(gè)最小堆 KeyValueHeap,該數(shù)據(jù)結(jié)構(gòu)核心一個(gè) PriorityQueue 優(yōu)先級(jí)隊(duì)列癌淮,隊(duì)列里按照 Scanner 指向的 KeyValue 排序峰伙。

3.2.2 數(shù)據(jù)過濾

我們知道數(shù)據(jù)在內(nèi)存以及 HDFS 文件中存儲(chǔ)著,為了讀取這些數(shù)據(jù)该默,RegionServer 構(gòu)造了若干 Scanner 并組成了一個(gè)最小堆瞳氓,那么如何遍歷這個(gè)堆去過濾數(shù)據(jù)返回用戶想要的值呢。 我們假設(shè) HRegion 有4個(gè) Hfile栓袖,1個(gè) MemStore匣摘,那么最小堆內(nèi)有4個(gè) scanner 對(duì)象,我們以 scannerA-D 來代替這些 scanner 對(duì)象裹刮,同時(shí)假設(shè)我們需要查詢的 rowkey 為 rowA音榜。每一個(gè) scanner 內(nèi)部有一個(gè) current 指針,指向的是當(dāng)前需要遍歷的 KeyValue捧弃,所以這時(shí)堆頂部的 scanner 對(duì)象的 current 指針指向的就是 rowA(rowA:cf:colA)這條數(shù)據(jù)赠叼。通過觸發(fā) next() 調(diào)用,移動(dòng) current 指針违霞,來遍歷所有 scanner 中的數(shù)據(jù)嘴办。scanner 組織邏輯視圖如下圖所示。
圖3 scanner組織邏輯視圖A

第一次 next 請(qǐng)求买鸽,將會(huì)返回 ScannerA中的rowA:cf:colA涧郊,而后 ScannerA 的指針移動(dòng)到下一個(gè) KeyValue rowA:cf:colB,堆中的 Scanners 排序不變眼五;
第二次 next 請(qǐng)求妆艘,返回 ScannerA 中的 rowA:cf:colB彤灶,ScannerA 的 current 指針移動(dòng)到下一個(gè) KeyValue rowB:cf:ColA糕档,因?yàn)槎寻凑?KeyValue 排序可知 rowB 小于 rowA, 所以堆內(nèi)部戒幔,scanner 順序發(fā)生改變,改變之后如下圖所示


圖4 scanner組織邏輯視圖B

scanner 內(nèi)部數(shù)據(jù)完全檢索之后會(huì) close 掉存崖,或者 rowA 所有數(shù)據(jù)檢索完畢汽煮,則查詢下一條搏熄。默認(rèn)情況下返回的數(shù)據(jù)需要經(jīng)過 ScanQueryMatcher 過濾返回的數(shù)據(jù)需要滿足下面的條件

  • keyValue類型為put
  • 列是Scanner指定的列
  • 滿足filter過濾條件
  • 最新的版本
  • 未刪除的數(shù)據(jù)

如果 scan 的參數(shù)更加復(fù)雜,條件也會(huì)發(fā)生變化逗物,比如指定 scan 返回 Raw 數(shù)據(jù)的時(shí)候,打了刪除標(biāo)記的數(shù)據(jù)也要被返回瑟俭,這部分就不再詳細(xì)展開翎卓,至此讀流程基本解析完成,當(dāng)然本文介紹的還是很粗略摆寄,有興趣的同學(xué)可以自己研究這一部分源碼失暴。

四、讀優(yōu)化

在介紹讀流程之后微饥,我們?cè)俳Y(jié)合有贊業(yè)務(wù)上的實(shí)踐來介紹如何優(yōu)化讀請(qǐng)求逗扒,既然談到優(yōu)化,就要先知道哪些點(diǎn)可會(huì)影響讀請(qǐng)求的性能欠橘,我們依舊從客戶端和服務(wù)端兩個(gè)方面來深入了解優(yōu)化的方法矩肩。

4.1客戶端層面

HBase 讀數(shù)據(jù)共有兩種方式,Get 與 Scan肃续。
在通用層面黍檩,在客戶端與服務(wù)端建連需要與 zookeeper 通信,再通過 meta 表定位到 region 信息始锚,所以在初次讀取 HBase 的時(shí)候 rt 都會(huì)比較高刽酱,避免這個(gè)情況就需要客戶端針對(duì)表來做預(yù)熱,簡(jiǎn)單的預(yù)熱可以通過獲取 table 所有的 region 信息瞧捌,再對(duì)每一個(gè) region 發(fā)送一個(gè) Scan 或者 Get 請(qǐng)求棵里,這樣就會(huì)緩存 region 的地址;
rowkey 是否存在讀寫熱點(diǎn)姐呐,若出現(xiàn)熱點(diǎn)則失去分布式系統(tǒng)帶來的優(yōu)勢(shì)殿怜,所有請(qǐng)求都只落到一個(gè)或幾個(gè) HRegion 上,那么請(qǐng)求效率一定不會(huì)高曙砂; 讀寫占比是如何的稳捆。如果寫重讀輕,瀏覽服務(wù)端 RegionServer 日志發(fā)現(xiàn)很多 MVCC STUCK 這樣的字樣麦轰,那么會(huì)因?yàn)?MVCC 機(jī)制因?yàn)閷?Sync 到 WAL 不及時(shí)而阻塞讀乔夯,這部分機(jī)制比較復(fù)雜砖织,考慮之后分享給大家,這里不詳細(xì)展開末荐。

Get 請(qǐng)求優(yōu)化

  • 將 Ge t請(qǐng)求批量化侧纯,減少 rpc 次數(shù),但如果一批次的 Get 數(shù)量過大甲脏,如果遇到磁盤毛刺或者 Split 毛刺眶熬,則 Get 會(huì)全部失敗(不會(huì)返回部分成功的結(jié)果)块请,拋出異常娜氏。
  • 指定列族,標(biāo)識(shí)符墩新。這樣可以服務(wù)端過濾掉很多無用的 scanner贸弥,減少 IO 次數(shù),提高效率海渊,該方法同樣適用于 Scan绵疲。

Scan 請(qǐng)求優(yōu)化

  • 設(shè)定合理的 startRow 與 stopRow 。如果 scan 請(qǐng)求不設(shè)置這兩個(gè)值臣疑,而只設(shè)置 filter盔憨,則會(huì)做全表掃描。
  • 設(shè)置合理的 caching 數(shù)目讯沈, scan.setCaching(100)郁岩。 因?yàn)?Scan 潛在會(huì)掃描大量數(shù)據(jù),因此客戶端發(fā)起一次 Scan 請(qǐng)求缺狠,實(shí)際并不會(huì)一次就將所有數(shù)據(jù)加載到本地驯用,而是分成多次 RPC 請(qǐng)求進(jìn)行加載。默認(rèn)值是100儒老。用戶如果確實(shí)需要掃描海量數(shù)據(jù)蝴乔,同時(shí)不做邏輯分頁處理,那么可以將緩存值設(shè)置到1000驮樊,減少 rpc 次數(shù)薇正,提升處理效率。如果用戶需要快速囚衔,迭代地獲取數(shù)據(jù)挖腰,那么將 caching 設(shè)置為50或者100就合理。

4.2 服務(wù)端優(yōu)化

相對(duì)于客戶端练湿,服務(wù)端優(yōu)化可做的比較多猴仑,首先我們列出有哪些點(diǎn)會(huì)影響服務(wù)端處理讀請(qǐng)求。

  • gc 毛刺
  • 磁盤毛刺
  • HFile 文件數(shù)目
  • 緩存配置
  • 本地化率
  • Hedged Read 模式是否開啟
  • 短路讀是否開啟
  • 是否做高可用

gc 毛刺沒有很好的辦法避免,通常 HBase 的一次 Young gc 時(shí)間在 20~30ms 之內(nèi)辽俗。磁盤毛刺發(fā)生是無法避免的疾渣,通常 SATA 盤讀 IOPS 在 150 左右,SSD 盤隨機(jī)讀在 30000 以上崖飘,所以存儲(chǔ)介質(zhì)使用 SSD 可以提升吞吐榴捡,變向降低了毛刺的影響。HFile 文件數(shù)目因?yàn)?flush 機(jī)制而增加朱浴,因 Compaction 機(jī)制減少吊圾,如果 HFile 數(shù)目過多,那么一次查詢可能經(jīng)過更多 IO 翰蠢,讀延遲就會(huì)更大项乒。這部分調(diào)優(yōu)主要是優(yōu)化 Compaction 相關(guān)配置,包括觸發(fā)閾值梁沧,Compaction 文件大小閾值檀何,一次參與的文件數(shù)量等等,這里不再詳細(xì)展開趁尼。讀緩存可以設(shè)置為為 CombinedBlockCache埃碱,調(diào)整讀緩存與 MemStore 占比對(duì)讀請(qǐng)求優(yōu)化同樣十分重要猖辫,這里我們配置 hfile.block.cache.size 為 0.4酥泞,這部分內(nèi)容又會(huì)比較艱深復(fù)雜,同樣不再展開啃憎。下面結(jié)合業(yè)務(wù)需求講下我們做的優(yōu)化實(shí)踐芝囤。
我們的在線集群搭建伊始,接入了比較重要的粉絲業(yè)務(wù)辛萍,該業(yè)務(wù)對(duì)RT要求極高悯姊,為了滿足業(yè)務(wù)需求我們做了如下措施。

4.2.1 異構(gòu)存儲(chǔ)

HBase 資源隔離+異構(gòu)存儲(chǔ)贩毕。SATA 磁盤的隨機(jī) iops 能力悯许,單次訪問的 RT,讀寫吞吐上都遠(yuǎn)遠(yuǎn)不如 SSD辉阶,那么對(duì)RT極其敏感業(yè)務(wù)來說先壕,SATA盤并不能勝任,所以我們需要HBase有支持SSD存儲(chǔ)介質(zhì)的能力谆甜。
為了 HBase 可以支持異構(gòu)存儲(chǔ)垃僚,首先在 HDFS 層面就需要做響應(yīng)的支持,在 HDFS 2.6.x 以及之后的版本规辱,提供了對(duì)SSD上存儲(chǔ)文件的能力谆棺,換句話說在一個(gè) HDFS 集群上可以有SSD和SATA磁盤并存,對(duì)應(yīng)到 HDFS 存儲(chǔ)格式為 [ssd] 與 [disk]罕袋。然而 HBase 1.2.6 上并不能對(duì)表的列族和 RegionServer 的 WAL 上設(shè)置其存儲(chǔ)格式為 [ssd]改淑, 該功能在社區(qū) HBase 2.0 版本之后才開放出來碍岔,所以我們從社區(qū) backport 了對(duì)應(yīng)的 patch ,打到了我們有贊自己的 HBase 版本之上溅固。支持 [ssd] 的 社區(qū)issue 如下: https://issues.apache.org/jira/browse/HBASE-14061?jql=text%20~%20%22storage%20policy%22 付秕。
添加SSD磁盤之后,HDFS集群存儲(chǔ)架構(gòu)示意圖如圖5所示:

圖5 混合機(jī)型下HDFS集群存儲(chǔ)邏輯示意圖

理想的混合機(jī)型集群異構(gòu)部署侍郭,對(duì)于 HBase 層面來看询吴,文件存儲(chǔ)可選三種策略:HOT, ONE_SSD, ALL_SSD,其中 ONE_SSD 存儲(chǔ)策略既可以把三個(gè)副本中的兩個(gè)存儲(chǔ)到便宜的SATA磁盤介質(zhì)之上來減少 SSD 磁盤存儲(chǔ)成本的開銷,同時(shí)在數(shù)據(jù)讀取訪問本地 SSD 磁盤上的數(shù)據(jù)可以獲得理想的 RT 亮元,是一個(gè)十分理想的存儲(chǔ)策略猛计。HOT 存儲(chǔ)策略與不引入異構(gòu)存儲(chǔ)時(shí)的存儲(chǔ)情況沒有區(qū)別,而 ALL_SSD 將所有副本都存儲(chǔ)到 SSD 磁盤上爆捞。 在有贊我們目前沒有這樣的理想混合機(jī)型奉瘤,只有純 SATA 與 純 SSD 兩種大數(shù)據(jù)機(jī)型,這樣的機(jī)型對(duì)應(yīng)的架構(gòu)與之前會(huì)有所區(qū)別煮甥,存儲(chǔ)架構(gòu)示意圖如圖6所示盗温。

圖6 純 SATA 與純 SSD 機(jī)型 HDFS 集群存儲(chǔ)架構(gòu)邏輯示意圖

基于這樣的場(chǎng)景,我們做了如下規(guī)劃:1.將SSD機(jī)器規(guī)劃成獨(dú)立的組成肘,分組的 RegionServer 配置 hbase.wal.storage.policy=ONE_SSD, 保證 wal 本身的本地化率卖局;2. 將SSD分組內(nèi)的表配置成 ONE_SSD 或者 ALL_SSD;3. 非SSD分組內(nèi)的表存儲(chǔ)策略使用默認(rèn)的 HOT 具體的配置策略如下:
在 hdfs-site.xml 中修改

在 SSD 機(jī)型 的 RegionServer 中的 hbase-site.xml 中修改

其中ONE_SSD 也可以替代為 ALL_SSD双霍。 SATA 機(jī)型的 RegionServer 則不需要修改或者改為 HOT 砚偶。

4.2.2 HDFS短路讀

該特性由 HDFS-2246 引入。我們集群的 RegionServer 與 DataNode 混布洒闸,這樣的好處是數(shù)據(jù)有本地化率的保證染坯,數(shù)據(jù)第一個(gè)副本會(huì)優(yōu)先寫本地的 Datanode。在不開啟短路讀的時(shí)候丘逸,即使讀取本地的 DataNode 節(jié)點(diǎn)上的數(shù)據(jù)单鹿,也需要發(fā)送RPC請(qǐng)求,經(jīng)過層層處理最后返回?cái)?shù)據(jù)深纲,而短路讀的實(shí)現(xiàn)原理是客戶端向 DataNode 請(qǐng)求數(shù)據(jù)時(shí)仲锄,DataNode 會(huì)打開文件和校驗(yàn)和文件,將兩個(gè)文件的描述符直接傳遞給客戶端囤萤,而不是將路徑傳遞給客戶端昼窗。客戶端收到兩個(gè)文件的描述符之后涛舍,直接打開文件讀取數(shù)據(jù)澄惊,該特性是通過 UNIX Domain Socket進(jìn)程間通信方式實(shí)現(xiàn),流程圖如圖7所示。


圖7 短路讀流程圖

該特性內(nèi)部實(shí)現(xiàn)比較復(fù)雜掸驱,設(shè)計(jì)到共享內(nèi)存段通過 slot 放置副本的狀態(tài)與計(jì)數(shù)肛搬,這里不再詳細(xì)展開。

開啟短路讀需要修改 hdfs-site.xml 文件

4.2.3 HDFS Hedged read

當(dāng)我們通過短路讀讀取本地?cái)?shù)據(jù)因?yàn)榇疟P抖動(dòng)或其他原因讀取數(shù)據(jù)一段時(shí)間內(nèi)沒有返回毕贼,去向其他 DataNode 發(fā)送相同的數(shù)據(jù)請(qǐng)求温赔,先返回的數(shù)據(jù)為準(zhǔn),后到的數(shù)據(jù)拋棄鬼癣,這也可以減少磁盤毛刺帶來的影響陶贼。默認(rèn)該功能關(guān)閉,在HBase中使用此功能需要修改 hbase-site.xml

線程池大小可以與讀handler的數(shù)目相同待秃,而超時(shí)閾值不適宜調(diào)整的太小拜秧,否則會(huì)對(duì)集群和客戶端都增加壓力。同時(shí)可以通過 Hadoop 監(jiān)控查看 hedgedReadOpshedgedReadOps 兩個(gè)指標(biāo)項(xiàng)章郁,查看啟用 Hedged read 的效果枉氮,前者表示發(fā)生了 Hedged read 的次數(shù),后者表示 Hedged read 比原生讀要快的次數(shù)暖庄。

4.2.4 高可用讀

HBase是一個(gè)CP系統(tǒng)聊替,同一個(gè)region同一時(shí)刻只有一個(gè)regionserver提供讀寫服務(wù),這保證了數(shù)據(jù)的一致性培廓,即不存在多副本同步的問題惹悄。但是如果一臺(tái)regionserver發(fā)聲宕機(jī)的時(shí)候,系統(tǒng)需要一定的故障恢復(fù)時(shí)間deltaT, 這個(gè)deltaT時(shí)間內(nèi)医舆,region是不提供服務(wù)的俘侠。這個(gè)deltaT時(shí)間主要由宕機(jī)恢復(fù)中需要回放的log的數(shù)目決定象缀。集群復(fù)制原理圖如下圖8所示蔬将。


圖8 HBase Replication 原理圖

HBase提供了HBase Replication機(jī)制,用來實(shí)現(xiàn)集群間單方向的異步數(shù)據(jù)復(fù)制我們線上部署了雙集群央星,備集群 SSD 分組和主集群 SSD 分組有相同的配置霞怀。當(dāng)主集群因?yàn)榇疟P,網(wǎng)絡(luò)莉给,或者其他業(yè)務(wù)突發(fā)流量影響導(dǎo)致某些 RegionServer 甚至集群不可用的時(shí)候毙石,就需要提供備集群繼續(xù)提供服務(wù),備集群的數(shù)據(jù)可能會(huì)因?yàn)?HBase Replication 機(jī)制的延遲颓遏,相比主集群的數(shù)據(jù)是滯后的徐矩,按照我們集群目前的規(guī)模統(tǒng)計(jì),平均延遲在 100ms 以內(nèi)叁幢。所以為了達(dá)到高可用滤灯,粉絲業(yè)務(wù)可以接受復(fù)制延遲,放棄了強(qiáng)一致性,選擇了最終一致性和高可用性鳞骤,在第一版采用的方案如下


圖9 客戶端高可用方案原理圖

粉絲業(yè)務(wù)方不想感知到后端服務(wù)的狀態(tài)窒百,也就是說在客戶端層面,他們只希望一個(gè) Put 或者 Get 請(qǐng)求正常送達(dá)且返回預(yù)期的數(shù)據(jù)即可豫尽,那么就需要高可用客戶端封裝一層降級(jí)篙梢,熔斷處理的邏輯,這里我們采用 Hystrix 做為底層熔斷處理引擎美旧,在引擎之上封裝了 HBase 的基本 API渤滞,用戶只需要配置主備機(jī)房的 ZK 地址即可,所有的降級(jí)熔斷邏輯最終封裝到 ha-hbase-client 中榴嗅,原理類似圖9蔼水,這里不再贅述。

4.2.5 預(yù)熱失敗問題修復(fù)

應(yīng)用冷啟動(dòng)預(yù)熱不生效問題录肯。該問題產(chǎn)生的背景在于應(yīng)用初始化之后第一次訪問 HBase 讀取數(shù)據(jù)時(shí)候需要做尋址趴腋,具體流程見圖2,這個(gè)過程涉及多次 RPC 請(qǐng)求论咏,所以耗時(shí)較長(zhǎng)优炬。在緩存下所有的 Region 地址之后,客戶端與 RegionServer 就會(huì)做點(diǎn)對(duì)點(diǎn)通信厅贪,這樣 RT 就有所保證蠢护。所以我們會(huì)在應(yīng)用啟動(dòng)的時(shí)候做一次預(yù)熱操作,而預(yù)熱操作我們通常做法是調(diào)用方法 getAllRegionLocations 养涮。在1.2.6版本getAllRegionLocations 存在 bug(后來經(jīng)過筆者調(diào)研葵硕,1.3.x,以及2.x版本也都有類似問題)贯吓,該方案預(yù)期返回所有的 Region locations 并且緩存這些 Region 地址懈凹,但實(shí)際上,該方法只會(huì)緩存 table 的第一個(gè) Region悄谐, 筆者發(fā)現(xiàn)此問題之后反饋給社區(qū)介评,并提交了 patch 修復(fù)了此問題,issue連接:https://issues.apache.org/jira/browse/HBASE-20697?filter=-2 爬舰。這樣通過調(diào)用修復(fù) bug 之后的 getAllRegionLocations 方法们陆,即可在應(yīng)用啟動(dòng)之后做好預(yù)熱,在應(yīng)用第一次讀寫HBase時(shí)便不會(huì)產(chǎn)生 RT 毛刺情屹。
粉絲業(yè)務(wù)主備超時(shí)時(shí)間都設(shè)置為 300ms坪仇。經(jīng)過這些優(yōu)化,其批量 Get 請(qǐng)求 99.99% 在 20ms 以內(nèi)垃你,99.9999% 在 400ms 以內(nèi)椅文。

五颈墅、總結(jié)

HBase 讀路徑相比寫路徑更加復(fù)雜,本文只是簡(jiǎn)單介紹了核心思路雾袱。也正是因?yàn)檫@種復(fù)雜性恤筛,在考慮優(yōu)化的時(shí)候需要深入了解其原理,且目光不能僅僅局限于本身的服務(wù)組件芹橡,也要考慮其依賴的組件毒坛,是否也有可優(yōu)化的點(diǎn)。最后林说,本人能力有限煎殷,文中觀點(diǎn)難免存在紕漏,還望交流指正腿箩。

最后打個(gè)小廣告豪直,有贊大數(shù)據(jù)團(tuán)隊(duì)基礎(chǔ)設(shè)施團(tuán)隊(duì),主要負(fù)責(zé)有贊的數(shù)據(jù)平臺(tái)(DP), 實(shí)時(shí)計(jì)算(Storm, Spark Streaming, Flink)珠移,離線計(jì)算(HDFS,YARN,HIVE, SPARK SQL)弓乙,在線存儲(chǔ)(HBase),實(shí)時(shí) OLAP(Druid) 等數(shù)個(gè)技術(shù)產(chǎn)品钧惧,歡迎感興趣的小伙伴聯(lián)系 zhaoyuan@youzan.com

參考
http://www.nosqlnotes.com/technotes/hbase/hbase-read/
http://hbasefly.com/2016/11/11/ http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/ShortCircuitLocalReads.html https://www.cloudera.com/documentation/enterprise/5-6-x/topics/admin_hedged_reads.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末暇韧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子浓瞪,更是在濱河造成了極大的恐慌懈玻,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乾颁,死亡現(xiàn)場(chǎng)離奇詭異涂乌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)英岭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門湾盒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巴席,你說我怎么就攤上這事历涝∽缧瑁” “怎么了漾唉?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)堰塌。 經(jīng)常有香客問我赵刑,道長(zhǎng),這世上最難降的妖魔是什么场刑? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任般此,我火速辦了婚禮蚪战,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘铐懊。我一直安慰自己邀桑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布科乎。 她就那樣靜靜地躺著壁畸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪茅茂。 梳的紋絲不亂的頭發(fā)上捏萍,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音空闲,去河邊找鬼令杈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛碴倾,可吹牛的內(nèi)容都是我干的逗噩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼跌榔,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼给赞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起矫户,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤片迅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后皆辽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柑蛇,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年驱闷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耻台。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡空另,死狀恐怖盆耽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扼菠,我是刑警寧澤摄杂,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站循榆,受9級(jí)特大地震影響析恢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜秧饮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一映挂、第九天 我趴在偏房一處隱蔽的房頂上張望泽篮。 院中可真熱鬧,春花似錦柑船、人聲如沸帽撑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽油狂。三九已至,卻和暖如春寸癌,著一層夾襖步出監(jiān)牢的瞬間专筷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工蒸苇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留磷蛹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓溪烤,卻偏偏與公主長(zhǎng)得像味咳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子檬嘀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容