最近在線上往hbase導數據,由於hbase寫入能力比較強,沒有太在乎寫的問題。讓業務方進行歷史數據的導入操做,中間發現一個問題,寫入速度太快,而且業務數據集中到其中一個region,這個region沒法split掉,處於不可用狀態。這裏描述一整個過程——算法
事情的原由:業務方按照userid和商品id做爲rowkey前綴,並無進行hash散列。我當時諮詢過業務方,認爲:1.業務方式按照oracle的rowid順序來進行遷移的,相對來講對應到rowkey裏面就不會集中化;2.即便出現部分集中的狀況,hbase也可以經過自動split來hold住寫入。oracle
結果線上寫入的時候,12臺機器的狀況下業務方寫入達到50~60w tps,基本上5w tps每臺的寫入速度。開始的時候region還可以自動split,比較好,寫入速度也可以保持,可是到了次日,發現寫入在region維度的分佈很不均衡,因而查看錶的region size 狀況,有一個region數據量特別大——800GB,700+個文件。.net
這裏也分析一下爲何hbase會讓這麼大的region存在,其實這塊hbase的控制機制也是值得商榷的。首先,大量的寫入會刷大量的HFile,一個region就會對這大量的hfile進行compact操做。若是這時候觸發了split操做,這個region會成爲父region,而兩個子region會保留父region的引用文件。而在這其間,子region會繼續寫入數據。那麼又可能觸發子region的compact,這裏的關鍵點來了——子region若是作compact的文件都是新寫入的文件,而遲遲不去compact父region 引用的文件,會致使一個問題——就是這個子region沒法被split掉了(由於含有父region引用的region是不能被split的)。那麼子region愈來愈大,因爲寫入文件數量急劇增加,父region的ref文件總也得不到機會compact,就造成了大region的惡性循環狀況——因爲region太大,compact沒法完成,可是因爲compact沒法完成致使region沒法split,沒法分攤compact的壓力給其餘regionserver。固然還得加上最後一點外部大量的寫入沒有中止——這裏咱們一般理解,hbase有一個參數hbase.hstore.blockingStoreFiles=30,當region下的hfile達到30個的時候是會阻塞寫的。那我都bolck住寫了,爲何region裏hfile會到700這麼多呢?原來還有另外一個參數hbase.hstore.blockingWaitTime=30000.hbase考慮到對應用的影響不會長時間block住寫,30秒後會恢復。server
這裏天梧有提一個改進的compact算法,優先去compact從父region引用過來的hfile,讓region有split的可能,能在必定程度上緩解這個問題http://kelude.taobao.net/issues/543434 ,這個方法我使用過,只能在必定程度上緩解問題,對於800G大小的region,一天都沒有compact掉。因此只適合100G之內的region,而且這時候業務方還不能有大量的寫操做。但有趣的是通常如此程度的寫入壓力都是在業務方新導入數據的時候形成的,因此和業務方溝通一下讓他們重導數據比本身慢慢鬱悶的compact這個大region來的要快的多。可是在從新導以前就要好好改進一下了:md5
這裏總結一下這個問題,對於大批量導入數據,一、仍是必須讓業務方對rowkey進行預分片,對業務數據rowkey進行md5或者其餘的hash策略,讓數據儘可能隨機分佈而不是順序寫入。二、隨時觀察region的大小,是否出現大region的狀況。get
這個問題預防爲主,若是出現大region——優先考慮重導數據,其次使用patch。hash