为什么要设计rowKey
首先要弄明白一点,Regions的分区就是根据数据的rowKey处理的,而如果设计rowKey不合理,就会导致所有数据到一个分区,或者并没有很好地发挥预分区带来的负载均衡作用,还是会发生数据倾斜。
HBase中还有一个就是rowKey的热点问题,因为rowKey是根据字典顺序排序的,如果rowKey设计不合理,当大量的client访问hbase集群的一个或少数几个节点,造成少数region server的读/写请求过多、负载过大,而其他region server负载却很小,就造成了“热点”现象。
热点问题会造成热点region所在的单个主机负载过大,引起性能下降甚至region不可用。
而热点问题产生的原因一般是因为大量连续编号的rowKey,导致相近的记录存在个别Region中,当client检索此类记录时,可能只会调用个别Region,大量访问将会导致此Region所在的主机过载。
下面就说一下rowKey设计的三个原则和热点问题的解决办法。
三大原则
长度原则
1.rowKey是二进制码流,可以是任意字符串,最大长度是64kb,实际应用一般为10-100 bytes,以 byte[] 形式保存
2.所以rowKey不能设计得过长,否则会导致占用内存空间过大,限制就是上面提到的64kb
散列原则
1.一般建议将rowKey的高位设置为散列字段,由系统随机生成什么是高位?就是rowKey的前面几个数字,如果前面几个为散列字段,就大大降低了相似记录和数据使用大量连续编号rowKey的问题
2.低位放时间字段,因为如果高位为时间字段,还是会导致热点问题,解决热点问题的核心就是不要让所有相似数据集中在一个RegionServer上
唯一原则
很简单,rowKey必须为唯一,因为如果出现重复的rowKey,最新存储的会将之前相同rowKey的数据作一次更新替换
热点问题的解决
加盐
通俗地说,就是在rowKey前面加随机数,这样能让rowKey随机生成分布到各个Region上
比如现在又三条数据,1111,1112,1113,如果不对其做处理,那这三条数据都会发送到同一个Region中,如果进行加盐,变成了 2341_1111,4232_1112,6442_1113,这样三条数据就会随机分布
哈希
哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的rowkey,可以使用get操作准确获取某一个行数据。
反转
就是反转固定长度或数字格式的rowKey,手机号就是最好的例子,因为我们知道同一运营商的后四位一般不会重复,而前三位会有大量重复,所以将其反转就可以快速有效地得到随机rowKey,但是这样也牺牲了rowKey的有序性
时间戳反转
一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为rowkey的一部分对这个问题十分有用,可以用 Long.Max_Value - timestamp 追加到key的末尾,例如 [key][reverse_timestamp] , [key] 的最新值可以通过scan [key]获得[key]的第一条记录,因为HBase中rowkey是有序的,第一条记录是最后录入的数据。