python寫(xiě)Hhbase超時(shí)問(wèn)題分析

Hbase是一個(gè)高可靠、高性能、面向列、可伸縮的分布式數(shù)據(jù)庫(kù)。其底層的LSM數(shù)據(jù)結(jié)構(gòu)和RowKey有序排列等架構(gòu)上的獨(dú)特設(shè)計(jì),使得hbase具有非常高的寫(xiě)入性能。但是在實(shí)際使用中,由于對(duì)hbase的寫(xiě)入方面的機(jī)制沒(méi)有深入的了解,無(wú)法有效發(fā)揮出hbase的寫(xiě)入性能。本文主要記錄了在剛開(kāi)始使用hbase時(shí),對(duì)hbase沒(méi)有太多的了解的基礎(chǔ)上,在寫(xiě)入方面遇到的一個(gè)問(wèn)題和解決方法。

Hbase原生支持java寫(xiě)入,但由于實(shí)際業(yè)務(wù)的需要和遷移的成本,要使用python來(lái)寫(xiě)入hbase。hbase中集成了thrift框架,支持使用python對(duì)hbase進(jìn)行操作。happybase是 FaceBook 員工開(kāi)發(fā)的操作HBase的 Python庫(kù),其基于 Thrift,封裝了大多數(shù)hbase的操作方法,使得通過(guò)python也能對(duì)hbase進(jìn)行操作。

問(wèn)題描述

在初步安裝好6個(gè)RS的Hbase集群上,新建一張測(cè)試表,使用200G的數(shù)據(jù),進(jìn)行寫(xiě)入性能的測(cè)試。
采用happybase寫(xiě)入hbase,下面是一段簡(jiǎn)化的代碼:

      (con, table) = get_hbase_con(table_name=table_name)
    with table.batch(batch_size=200) as batch:
        with open(filepath) as fp:
            for line in fp:
                records = line.strip().split(',')
                  cf={"cf:data":records}
                batch.put(row=rowkey, data=cf)

Happybase的put方法原本就是采用batch批量提交數(shù)據(jù),在代碼中使用table.batch可以自己控制batch_size的大小。采用batch提交,減少rpc請(qǐng)求次數(shù),提高寫(xiě)入的性能。

運(yùn)行程序時(shí),程序通過(guò)socket與hbase的thriftsever連接,將請(qǐng)求發(fā)給thriftsever,由thriftsever調(diào)用hbase的client端進(jìn)行寫(xiě)入。使用單線(xiàn)程進(jìn)行數(shù)據(jù)的寫(xiě)入一段時(shí)間之后,總會(huì)出現(xiàn)socket.timeout的問(wèn)題。一旦出現(xiàn)該問(wèn)題后,程序終止運(yùn)行,如下圖所示:

出現(xiàn)此問(wèn)題時(shí),寫(xiě)入的每秒請(qǐng)求數(shù)才5200多,并且是持續(xù)的向一個(gè)region中寫(xiě)入。


問(wèn)題分析和解決

為了解決這個(gè)問(wèn)題,我安裝了ganglia監(jiān)控工具。在寫(xiě)入的時(shí)候,查看集群上的指標(biāo),發(fā)現(xiàn)寫(xiě)入的節(jié)點(diǎn)上負(fù)載過(guò)重,cpu利用率飆升,其它節(jié)點(diǎn)基本處于休眠狀態(tài)。由此現(xiàn)象可以初步斷定是hbase寫(xiě)入的熱點(diǎn)問(wèn)題造成了timeout。解決hbase的熱點(diǎn)問(wèn)題,關(guān)鍵在于rowkey的設(shè)計(jì)和預(yù)分區(qū)上。

Hbase的RowKey是按字點(diǎn)排序由低到高進(jìn)行存儲(chǔ)的,在設(shè)計(jì)時(shí)需要遵循散列性,唯一性,同時(shí)也要兼顧實(shí)際業(yè)查詢(xún)的需求,這樣在寫(xiě)入的過(guò)程中不至于造成一臺(tái)集群負(fù)載過(guò)重的情況。

現(xiàn)有的RowKey的設(shè)計(jì)規(guī)則如下:



很明顯其是按時(shí)間有序排列的,不符合rowkey的散列性,原始數(shù)據(jù)是按時(shí)間順序排列的,在插入時(shí),就會(huì)一直向同一個(gè)region中插入,因此造成熱點(diǎn)問(wèn)題。通過(guò)改進(jìn),將后面的標(biāo)示位放置rowkey的前綴,由于標(biāo)示位是散列的,沒(méi)有規(guī)律,RowKey的設(shè)計(jì)變成了:
RowKey = 標(biāo)示位+預(yù)留10位+時(shí)間戳
清空測(cè)試表后,重新插入數(shù)據(jù)測(cè)試,發(fā)現(xiàn)插入時(shí)仍然會(huì)出現(xiàn)熱點(diǎn)問(wèn)題。繼續(xù)進(jìn)行分析,查到一段話(huà):

默認(rèn)情況下,當(dāng)我們通過(guò)hbaseAdmin指定TableDescriptor來(lái)創(chuàng)建一張表時(shí),只有一個(gè)region正處于混沌時(shí)期,start-end key無(wú)邊界,可謂海納百川。所有的rowkey都寫(xiě)入到這個(gè)region里,然后數(shù)據(jù)越來(lái)越多,region的size越來(lái)越大時(shí),大到一定的閥值,hbase就會(huì)將region一分為二,成為2個(gè)region,這個(gè)過(guò)程稱(chēng)為分裂(region-split)。
如果我們就這樣默認(rèn)建表,表里不斷的put數(shù)據(jù),更嚴(yán)重的是我們的rowkey還是順序增大的,是比較可怕的。存在的缺點(diǎn)比較明顯:首先是熱點(diǎn)寫(xiě),我們總是向最大的start key所在的region寫(xiě)數(shù)據(jù),因?yàn)槲覀兊膔owkey總是會(huì)比之前的大,并且hbase的是按升序方式排序的。所以寫(xiě)操作總是被定位到無(wú)上界的那個(gè)region中;其次,由于熱點(diǎn),我們總是往最大的start key的region寫(xiě)記錄,之前分裂出來(lái)的region不會(huì)被寫(xiě)數(shù)據(jù),有點(diǎn)打入冷宮的感覺(jué),他們都處于半滿(mǎn)狀態(tài),這樣的分布也是不利的。
hbase熱點(diǎn)問(wèn)題(數(shù)據(jù)傾斜)解決方案—rowkey散列和預(yù)分區(qū)設(shè)計(jì) - - ITeye技術(shù)網(wǎng)站

按照這個(gè)解釋?zhuān)词箤?duì)rowkey進(jìn)行散列化設(shè)計(jì),仍然不能解決熱點(diǎn)問(wèn)題,初始建表沒(méi)有進(jìn)行預(yù)分區(qū)時(shí),只有一個(gè)region,其并沒(méi)有一個(gè)上界,導(dǎo)致在插入時(shí)還是不斷的向一個(gè)region中插入。因此接下的操作是進(jìn)行表進(jìn)行預(yù)分區(qū)。
由于RowKey的設(shè)計(jì)已經(jīng)變成了散列性,導(dǎo)致預(yù)分區(qū)不好確定每個(gè)region的RowKey范圍。針對(duì)此問(wèn)題,在有限的數(shù)據(jù)中,采取了將所有的rowkey提取出來(lái)排序后,分段抽取的方式,確定了每個(gè)region的范圍。

通過(guò)rowkey的散列化和預(yù)分區(qū),每個(gè)節(jié)點(diǎn)上都啟動(dòng)ThrfftServer服務(wù),將200G的大文件拆成了多個(gè)小文件,然后采用python的多進(jìn)程再次進(jìn)行測(cè)試。此時(shí)出現(xiàn)了可喜的結(jié)果,

從圖可以看到,寫(xiě)入的請(qǐng)求分布的比較均勻,不再集中到一個(gè)region 上。從ganglia上的監(jiān)控上看,單個(gè)節(jié)點(diǎn)的負(fù)載比之前有很大的下降。到此,hbase的寫(xiě)入熱點(diǎn)問(wèn)題基本上解決。
從圖可以看到,寫(xiě)入的請(qǐng)求分布的比較均勻,不再集中到一個(gè)region 上。從ganglia上的監(jiān)控上看,單個(gè)節(jié)點(diǎn)的負(fù)載比之前有很大的下降。到此,hbase的寫(xiě)入熱點(diǎn)問(wèn)題基本上解決。

但是timeout的情況依然出現(xiàn),出現(xiàn)時(shí)間較之前有延后,可見(jiàn)問(wèn)題并沒(méi)有徹底的解決。timeout出現(xiàn)時(shí)間延后,說(shuō)明解決hbase寫(xiě)入的熱點(diǎn)問(wèn)題對(duì)timeout問(wèn)題是有幫助的。

因此我對(duì)hbase的寫(xiě)入過(guò)程中進(jìn)行了更加深入的分析,看看數(shù)據(jù)在寫(xiě)入的過(guò)程中究竟發(fā)生了什么。
Hbase寫(xiě)入過(guò)程包括了客戶(hù)端和服務(wù)端,采用客戶(hù)端批量寫(xiě)入數(shù)據(jù),數(shù)據(jù)會(huì)現(xiàn)在本地的buffer中緩存,到達(dá)閾值后,客戶(hù)端就會(huì)將數(shù)據(jù)推送到服務(wù)端,服務(wù)端收到數(shù)據(jù)后先寫(xiě)日志,然后在寫(xiě)入memstore中,memstore滿(mǎn)后就會(huì)flush到storefiles,當(dāng)storefiles 的數(shù)量增長(zhǎng)到一定閾值后,就會(huì)進(jìn)行compact成更大的storefile,當(dāng)storefile達(dá)到閾值后就會(huì)split成兩個(gè)region,被hmaster分配到其它的regionserver中。

由于寫(xiě)入過(guò)快,服務(wù)器端需要大量compact,split操作時(shí),很容易阻塞數(shù)據(jù)的寫(xiě)入,會(huì)出現(xiàn)has too many store files; delaying flush up to 90000ms等問(wèn)題。一旦出現(xiàn)服務(wù)端阻塞寫(xiě)入的問(wèn)題,client端就會(huì)延遲收到響應(yīng)結(jié)果。如果在規(guī)定的時(shí)間內(nèi),客戶(hù)端仍未接收到服務(wù)器端的響應(yīng),socket就會(huì)出現(xiàn)timeout的情況,然后客戶(hù)端和服務(wù)器端的連接就會(huì)斷掉,寫(xiě)入過(guò)程終止。通過(guò)對(duì)日志的分析,也說(shuō)明了出現(xiàn)timeout的問(wèn)題時(shí),hbase正在進(jìn)行compact或split操作。

從上述的分析中,明確了解決timeout問(wèn)題的下一步目標(biāo)是優(yōu)化hbase的寫(xiě)入性能。通過(guò)對(duì)hbase的region size、rpc超時(shí)時(shí)間、scanner超時(shí)時(shí)間、memstore fluse size、blockingStoreFiles等參數(shù)優(yōu)化,降低compact和split的頻率,延遲超時(shí)出現(xiàn)的時(shí)間,也降低了超時(shí)的頻率。

除非全部手動(dòng)進(jìn)行,hbase進(jìn)行compact和split是不可避免的,因此寫(xiě)入超時(shí)也是不可避免的。從happybase的githup上找到了解決timeout一勞永逸的方法,將客戶(hù)端的timeout置為不限。thriftpy0.3.3設(shè)置了默認(rèn)的超時(shí)時(shí)間為3s,要想永不超時(shí),將timeout設(shè)置為None即可。

Since thriftpy 0.3.3, there has been a socket_timeout option to TSocket. The default is 3000 ms. Setting it to None means “never timeout”. Remove the if self.timeout is not None conditional so a value of None can also be set explicitly from happybase.
Set socket timeout unconditionally on TSocket by ecederstrand · Pull Request #146 · wbolster/happybase · GitHub

# timeout = None
 con = happybase.Connection(host=host, autoconnect=False, timeout=None, transport='buffered')

網(wǎng)上有建議將timeout設(shè)置更長(zhǎng)一點(diǎn),但是由于網(wǎng)絡(luò)以及服務(wù)端的問(wèn)題不確定性,超時(shí)的風(fēng)險(xiǎn)很大。直接設(shè)置成None,客戶(hù)端就會(huì)一直等待服務(wù)端的響應(yīng),再也不會(huì)出現(xiàn)超時(shí)的問(wèn)題。

上述方法雖然一勞永逸,但是如果有潛在的風(fēng)險(xiǎn)就是一直阻塞。推薦采取手動(dòng)的處理超時(shí)問(wèn)題。在捕獲到超時(shí)后,選擇斷開(kāi)連接,暫停一小段時(shí)間寫(xiě)入,重新連接然后進(jìn)行寫(xiě)入。

總結(jié)

初入Hbase,作為一個(gè)小白,耗費(fèi)了較長(zhǎng)的時(shí)間才解決寫(xiě)入超時(shí)的問(wèn)題。一個(gè)問(wèn)題牽涉了Hbase的方方面面,使我收獲滿(mǎn)滿(mǎn):
1、更了解hbase的特點(diǎn),RowKey的設(shè)計(jì),表的預(yù)分區(qū)。
2、從源碼上了解Hbase的寫(xiě)入過(guò)程
4、如何優(yōu)化hbase性能
5、分析和解決問(wèn)題的思路

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,637評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,555評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,900評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,629評(píng)論 6 412
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,976評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評(píng)論 3 448
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,139評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,686評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,411評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,641評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,820評(píng)論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,233評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,567評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,362評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,604評(píng)論 2 380

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