介紹
Hbase每一條記錄是按照rowkey做為唯一辨別符設計的,rowkey按照字典順序排序,友善資料讀取掃描。衆所周知,資料是存儲在Region中,每個Region都包含rowkey開始和結束範圍,資料rowkey在哪個範圍尋找對應的Region進行存儲。
Region存儲範圍樣例:
Region | start-rowkey | end-rowkey | |
---|---|---|---|
region-01 | 1 | 10 | 存儲rowkey在1-10範圍内的資料 |
region-02 | 11 | 20 | 存儲rowkey在11-20範圍内的資料 |
region-03 | 21 | 30 | 存儲rowkey在21-30範圍内的資料 |
以上就是資料在各個Region中的存儲方式,這種設計在給資料讀寫帶來友善的同時,也帶來了一些其他負面問題。
資料熱點(Hotspotting)
Hbase資料按照rowkey進行存儲,雖然為查詢資料提供了極大便利,但同時也産生了其他問題,比如資料熱點(Hotspotting)問題。當大部分rowkey集中在某個範圍時,會導緻某幾個Region資料量很大,其他Region資料量很少,這就是資料傾斜問題。是以整個叢集壓力都集中在某幾個Region上,導緻讀寫性能大幅度下降,這就是資料熱點問題。資料熱點問題嚴重情況下會導緻Region下線,甚至整個叢集當機。
為了避免以上現象,我們需要将資料盡可能的均勻分布在各個Region中,是以Hbase中rowkey的設計至關重要。
rowkey設計原則
了解Hbase資料的存儲原理和rowkey的作用之後,rowkey的設計就成為了重中之重。通常rowkey設計要遵循長度、散列、唯一三大原則。
長度:rowkey是以ByteArray進行存儲,可以是任意字元。rowkey設計越短越好,建議在16位元組以下。由于在底層資料檔案中是按照key-value形式存儲的,如果rowkey按照100位元組,1000萬條資料,那麼僅rowkey就占用了将近1GB空間。
散列:散列性原則是通過rowkey将資料均勻分布在各個Region中,避免資料傾斜和熱點問題。
唯一:rowkey代表每一行記錄的主鍵,必須具有唯一性。
資料傾斜和熱點問題
資料傾斜和熱點是一個很常見的問題,往往給生産和維護帶來了很大困擾。那麼如何有效的避免或減少這種問題呢?答案就是優化rowkey設計,官方提供了以下幾種優化方案:
參考網址:官方網址 第35章節Rowkey Design
Salting
原理:一句話簡單描述為在rowkey前邊加上随機值,其中随機值數量是region的個數。
假設有四個rowkey
foo0001、foo0002、foo0003、foo0004
我們想要均勻分布在四個region中,假設有a、b、c、d四個salt,每個salt都在不同的region上。加入salt後rowkey就變成了
a-foo0003、b-foo0001、c-foo0004、d-foo0002
每一個rowkey都增加了随機salt字首,這樣就能減輕資料傾斜問題
缺點:由于資料增加了随機字首salt,是以查詢就變得更加複雜
Hashing
原理:為了彌補随機字首對查詢帶來的影響,引申出了一種one-way hash方法,保證相同的rowkey永遠都有相同的字首salt。
還是上邊的例子,這次将salt換成hash(rowkey),這樣同一個rowkey生成的salt永遠一樣,保障了查詢性能。
Reversing the Key
原理:将rowkey中經常變化的數字部分或者固定長度的部分做為字首,這樣增加了散列性,能夠有效減緩資料傾斜問題。
缺點:有可能喪失了原來rowkey的有序性,對資料查詢帶來影響。
建表時預分區
在建表時根據資料量和資料分布情況,合理的設定Region數量,設計合适的rowkey。這樣一方面能有效避免資料傾斜問題,還能防止Region頻繁分裂和合并帶來額外的IO開銷。
缺點:這種方式有很大的局限性,隻适合有限的資料量或者增長緩慢的場景。
byte[][] splitKeys = {
Bytes.toBytes("01"),
Bytes.toBytes("02"),
Bytes.toBytes("03"),
Bytes.toBytes("04")
};
List<String> families = new ArrayList<>();
families.add("f1");
hbaseManager.createTable("test", families, splitKeys);
水準一般,能力有限,大資料國小生一枚。文章主要用于個人學習和總結,如果能給他人帶來幫助,純屬意外。