HBase 熱點(diǎn)問題
剛創(chuàng)建 HBase 表的時候默認(rèn)只有一個 Region 由一個 Region Server 管理莹捡,在數(shù)據(jù)量達(dá)到一定值的時候會觸發(fā)分裂 split,這樣會不斷的分裂出更多的 Region,由不同的 Region Server 管理纲岭,每個 Region 管理的是一段連續(xù)的 row key晓淀,由 start row key 和 end row key 表示,這樣會有兩個問題
- 無法充分利用分布式并發(fā)處理的優(yōu)勢,必須等 Region 自動分裂成多個澈吨,這個過程可能會很久
- 由于每個 Region 管理一段連續(xù)的 row key把敢,這樣如果數(shù)據(jù)的讀寫不夠隨機(jī),比如有自增 ID谅辣,比如大量操作集中在某段 row key修赞,這樣有可能導(dǎo)致壓力都在同一個 Region 上
Region 分裂策略
定義在 hbase-site.xml 文件
<name>hbase.regionserver.region.split.policy</name>
<value>org.apache.hadoop.hbase.regionserver.IncreasingToUpperBoundRegionSplitPolicy</value>
<description>
A split policy determines when a region should be split. The various other split policies that
are available currently are ConstantSizeRegionSplitPolicy, DisabledRegionSplitPolicy,
DelimitedKeyPrefixRegionSplitPolicy, KeyPrefixRegionSplitPolicy etc.
</description>
默認(rèn)策略是 IncreasingToUpperBoundRegionSplitPolicy,在 HBase 1.2 中桑阶,這個策略默認(rèn)表示柏副,當(dāng) Region 的大小達(dá)到 Region 個數(shù)的立方乘以 hbase.hregion.memstore.flush.size(默認(rèn) 128 MB)再乘以 2 ,或是達(dá)到 hbase.hregion.max.filesize (默認(rèn) 10 GB)時联逻,就對該 Region 做分裂
第一次分裂的大写瓿丁:1^3 * 128MB * 2 = 256MB
第二次分裂的大小:2^3 * 128MB * 2 = 2048MB
第三次分裂的大邪椤:3^3 * 128MB * 2 = 6912MB
第四次分裂的大邢峭啤:4^3 * 128MB * 2 = 16384MB,超過了 10GB公壤,因此只取 10GB
后面的分裂大小都是 10GB
可以看到如果可以利用的節(jié)點(diǎn)比較多的話换可,那么可能得等很久才能充分利用
預(yù)分區(qū)
第一種預(yù)分區(qū)的方法
hbase org.apache.hadoop.hbase.util.RegionSplitter tablename HexStringSplit -c 10 -f f1:f2:f3
上面的命令表示創(chuàng)建一張名為 tablename 的表,這張表預(yù)先分配了 10 個 Region厦幅,有三個 CF沾鳄,分別是 f1、f2确憨、f3译荞,預(yù)分區(qū)算法是 HexStringSplit,也可以選擇 UniformSplit休弃,其中 HexStringSplit 適合 row key 的前綴是十六進(jìn)制的字符串的吞歼,UniformSplit 適合 row key 前綴完全隨機(jī)的,預(yù)分區(qū)后塔猾,哪怕連續(xù)的 row key篙骡, HBase 也會通過算法將其分到不同的 Region,實(shí)現(xiàn)均勻分布丈甸,避免了熱點(diǎn)
第二種預(yù)分區(qū)的方法
hbase shell > create 'tablename', 'f1', SPLITS=> ['10', '20', '30', '40']
當(dāng)可以提前知道 row key 的分布的時候糯俗,可以指定每個預(yù)分區(qū)的 region 的分割點(diǎn),上面命令創(chuàng)建的表中睦擂,有 5 個 Region
Region 1 : row key 的前兩位是 min~10
Region 2 : row key 的前兩位是 10~20
Region 3 : row key 的前兩位是 20~30
Region 4 : row key 的前兩位是 30~40
Region 5 : row key 的前兩位是 40~max
注意這里不單指數(shù)字字符得湘,比如 1a 就會落在 Region 2
對已存在的表可以做強(qiáng)制分裂
hbase shell > split 'table', 'split point'
此外也可以設(shè)計(jì)自己的分裂方法
Phoenix 加鹽
CREATE TABLE IF NOT EXISTS Product (
id VARCHAR not null,
time VARCHAR not null,
price FLOAT,
sale INTEGER,
inventory INTEGER,
CONSTRAINT pk PRIMARY KEY (id, time)
) COMPRESSION = 'GZ', SALT_BUCKETS = 6
本質(zhì)上是對 HBase 表的 row key 做了哈希后,對 SALT_BUCKETS 取余數(shù)祈匙,并將結(jié)果(上面的例子中是 0~5)作為 byte 插入到 row key 的第一位忽刽,根據(jù)這個數(shù)值將數(shù)據(jù)分到不同 Region 中天揖,由于是作為 byte 存儲,所以 SALT_BUCKETS 能取的最大值是 256跪帝,擁有相同 salt byte 的 row 會被分到相同的 region server今膊,所以通常取 region server 的數(shù)量作為 SALT_BUCKETS
由于加了鹽的數(shù)據(jù)最前面多了一位,這樣默認(rèn)情況下伞剑,從不同 region server 取出來的數(shù)據(jù)無法按原來的 row key 排序斑唬,如果需要保證排序,需要改一個配置
phoenix.query.force.rowkeyorder = true