HBase 順序序列rowkey和預分區規則的思考和設計

以往工作中HBase存儲海量數據時候,因為歷史原因主鍵使用自增長序列,數據遷移到HBase中時,并沒有改變主鍵策略。導致數據全部寫入一個region,造成數據熱點。當時也沒有采用預分區,數據增長過快,region過大時,在系統低負載時段需手動切分region。這些原因導致集群整體效率低。

現在要求

目前正好有一個新的數據存儲場景開始設計,對數據需要增量順序讀(如:增量構建全文索引等),中等規模隨機讀。能按照區間范圍順序查詢,并能控制查詢的開始和結束。以方便增量或重新構建索引或控制區間化數據讀取需求等等。總結歷史經驗和教訓, 現在需要考慮的2種場景:

  1. 海量文本數據A,天入庫數據量在30-200W左右,文本格式長,需要保存原文。(數量現對小,單文本容量比較大,需要保存原文)
  2. 海量文本數據B,天數據量在500w-5000w之間,文本格式短小。(數量現對多,單文本容量相對小 )

HBase基本情況

表和索引組成

  • HBase一般由行鍵(row key)、列鍵(column qualifier )、列族(column family)組成。行鍵對應關鍵數據庫中主鍵,HBase為行鍵建立了索引,列鍵歸屬列族。通過行鍵/列鍵/列族定位到一個唯一記錄。

  • HBase中使用.META內部表存儲region的分布情況以及每個region的詳細信息。region中記錄了rowkey范圍,region分散在不同服務器中。通過region server提供訪問數據訪問服務,region server可服務多個region,來自不同region server上的region組合成表格的整體邏輯視圖。

獲取記錄方式

  • 通過get方式,指定rowkey獲取唯一記錄
  • 通過scan方式,設置startRow和stopRow參數進行范圍匹配
  • 通過scan方式,全表掃描,并通過RowFilter過濾出數據
    基本可歸納為順序讀和隨機讀。

rowkey原則

長度原則

行鍵長度盡量短和合理,因為持久化文件HFile中使用KeyValue形式保存數據,column family/column qualifier/rowkey會記錄到每一條數據中,導致存儲文件過大,也會導MemStore內存有效利用率降低。rowkey使用byte[]保存數據,使用數值(long)比字符(String)占用更小空間。64為系統內存8字節對齊,控制在16個字節,盡量使用8為倍數。

散列原則避免熱點
  • 加鹽
    在rowkey前按規則加隨機數,使數據分散到不同region上避免熱點。也可通過業務規則分段比如:userid-service-timestamp,把不同userid或不同業務數據切分到不同region。
  • 哈希
    生成哈希或使用UUID散列它。
  • 反轉
    如果是順序序列可以反轉它,讓他經常改變的部分排到前面避免數據集中。時間反轉也可以考慮Long.Max_Value - timestamp。
唯一原則

主鍵都必須保證唯一。

分布式主鍵算法

分布式主鍵算法要求

  • 毫秒級的快速響應
  • 可用性強
  • prefix有連續性方便DB順序存儲
  • 體積小,8字節為佳

目前分布式主鍵算法比較

UUID

16字節,JAVA自帶,好用,占用空間大。

Twitter Snowflake

Snowflake: timestamp + work id + seq number

圖引用自其他Blog

8字節,可用性強,速度快。占用空間小,如果考慮復雜環境work id需要更好處理。twitter默認實現需要引入zookeeper 和獨立的snowflake專用服務器,UC實現通過配置文件確定work id。

MongoDB ObjectId

ObjectId:timestamp + machine + pid + seq number

圖引用自MongoDB 官方文檔

12字節,可用性強,速度快。占用空間中等,用空間降低實現復雜度,基本沒有其他依賴。

業務rowkey設計

業務的需求

  • 大文本A每分鐘最多1388條,每秒23條。
  • 小文本B每分鐘最多34722條,每秒578條。

考慮到大量順序讀,需要做到局部連續,全局分散。每秒極端情況寫數據量不多,可考慮按照分鐘分區。一共60個分區。獲取一天數據時候通過60*24=1440 按照1440個局部連續批來獲取數據。

rowkey規則1

參考snowflake和ObjectId原理,感覺它并不好直觀分區,所以:
partition + timestamp + work id+ seq number 增加分區,減少時間和work id范圍。
0-000000-01111111 10111111 11111000 00111100-00000000 0-00000000 00000000
1bit 不用
6bit 分區,可支持63個分區,可使用秒或分鐘做分區
32bit 時間 System.currentTimeMillis()到秒(可以用到2099年)
9bit 區分機器和進程,需要在存儲空間和復雜度上找平衡
16bit seq(最大65535)
全長64Bit,8Byte可做到不依賴其他服務。
分區可表示為:
0-000000-0000000 000000000 00000000 00000000-00000000 0-00000000 00000000
0-000001-0000000 000000000 00000000 00000000-00000000 0-00000000 00000000
0-000010-0000000 000000000 00000000 00000000-00000000 0-00000000 00000000
0-000011-0000000 000000000 00000000 00000000-00000000 0-00000000 00000000

rowkey規則2

規則1太復雜實現和可讀性低簡,簡化下
reverse timestamp(mmHHddMMyyyy)+ seq number(0-99999)
seq number使用redis保證全局唯一,每個客戶端使用步長減少redis訪問頻次。
例如:rowkey=20170719213012345表示為:30211907201712345使用分鐘做分區30表示分區。
分區可表示為:
1000000000000000L:11100011010111111010100100110001101000000000000000
3000000000000000L:111000110101111110101001001100011010000000000000000
59000000000000000L:11010001100111000010111111111001101111111000000000000000
56Bit,7Byte 依賴redis服務 簡單直觀可讀性好。

rowkey規則2順序讀取數據方式

假如我需要scan查詢2017/07/19數據,我需要從201707190000~201707192359
60*24=1440做循環。2017/07/19/ 21:35為例子, StartRow和StopRow設置如下:
StartRow=35211907201700000L
StopRow=35211907201799999L

最終選擇規則2作為rowkey規則,隨然依賴redis服務,但是存儲空間小、可讀性高、可理解性好、方便使用和維護。

其他

不考慮HBase RowFilter方式,希望的效果就是直接利用rowkey內部索引和.META表。對于其他復雜組合查詢,我傾向使用全文索引ES或Solr。

可以參考算法源碼

UC Snowflake

https://github.com/sumory/uc/blob/master/src/com/sumory/uc/id/IdWorker.java

MaongoDB ObjectID

https://github.com/mongodb/mongo-java-driver/blob/master/bson/src/main/org/bson/types/ObjectId.java

Email:wei.liu@qq.com
劉威 2017年7月19日 長沙

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

推薦閱讀更多精彩內容