用户侧策略:
在之前的会议中,建议应用侧优化row设计和预分区,下面具体说明:
1、rowkey的设计建议使用哈希、加盐、反转的方式使请求均匀的分布到每个节点上。
1.1、加盐。对某些业务来说,rowkey并不具有前缀散列性,如果以时间戳为前缀,就会导致短时间内写入的rowkey都在同一个region,造成数据热点。这个时候,我们一般会加一个前缀prefix,与原有rowkey拼接成新的rowkey。读取的时候,比如我要读Row0这个rowkey,那么就需要在读取00-Row0,01-Row0,02-Row0,03-Row0,04-Row0这五个rowkey,并且把结果归并起来。如图:
加盐的缺点,由于前缀是随机生成的,因而如果想要按照字典顺序找到这些行,则需要做更多的工作。从这个角度上看,salting增加了写操作的吞吐量,却也增大了读操作的开销。
1.2、哈希。加盐策略在get的时候,开销比较大,如果场景是即席查询为主,可以考虑使用hashing,在避免读写热点的同时,加快get操作的效率。确定性Hash(比如md5后取前4位做前缀)能让客户端重建完整的RowKey,可以使用get操作直接get想要的行。读取的时候,比如我要读Row0这个rowkey,通过hash函数可以直接计算出真实rowkey,从而直接get到结果。 如图:
哈希的缺点,虽然可以一定程度打散整个数据集,但是不利于Scan,Scan的时候取到的连续数据行没有前后联系。
1.3、反转,
有些类型的应用,rowkey带手机号,时间戳等,通过反转就可以有效的起到散列的效果。从某种程度上看,反转的效果类似于hash,对scan类查询不友好。不过对于时间戳或者手机号等特定类型的问题,反转可以做到较好地优化。一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为 rowkey 的一部分对这个问题十分有用,可以用 Long.Max_Value - timestamp 追加到 key 的末尾,例 如 [key][reverse_timestamp] , [key] 的最新值可以通过 scan [key]获得[key]的第一条记录,因为 HBase 中 rowkey 是有序的,第一条记录是最后录入的数据。比如需要保存一个用户的操 作记录,按照操作时间倒序排序,在设计 rowkey 的时候,可以这样设计 [userId 反转][Long.Max_Value - timestamp],在查询用户的所有操作记录数据的时候,直接指定反转后的 userId, startRow 是 [userId 反转 ][000000000000],stopRow 是 [userId 反 转][Long.Max_Value - timestamp]
如果需要查询某段时间的操作记录, startRow 是[user 反转][Long.Max_Value - 起始时间], stopRow 是[userId 反转][Long.Max_Value - 结束时间] ,这样范围查询的性能也不受影响。
2、预分区
Hbase中的表会被划分为n个Region,然后存放在多个RegionServer中,每个Region有StartKey和EndKey,表示这个Region维护的RowKey范围,而第一个Region没有StartKey,最后一个Region没有EndKey。需要读写数据时,RowKey会落在某个范围内,就会定位到目标的Region以及所在的RegionServer。
应用的表大部分表都是50个分区,每个分区的最大大小为10G,当1个分区达到最大后,会分裂成2个分区,并且分裂点由服务端自动选择,分裂后也很容易出现热点问题,建议应用根据表大小来评估预分区的数量。
预分区有手动和自动两种方法。其中系统支持的自动预分区有UniformSplit、DecimalStringSplit和HexStringSplit算法。UniformSplit在00到FF对应的随机字符中选取预分区点,后面两种分别在00000000 到 99999999.和00000000 到 FFFFFFFF中选取预分区点。
2.1、手动指定预分区断点:
hbase>create 't1','f1',SPLITS => ['\x10\x00', '\x20\x00', '\x30\x00', '\x40\x00']
2.2、使用随机字符指定4个预分区断点,分成5个预分区
hbase>create 't2','f1', { NUMREGIONS => 4 , SPLITALGO => 'UniformSplit' }
2.3、使用16进制字符指定5个预分区断点,分成6个预分区
create 't3','f1', { NUMREGIONS => 5, SPLITALGO => 'HexStringSplit' }
集群运维策略:
在实际使用过程中,不同表的冷热分布不均是很常见的行为,因为这个因素导致的region server热点问题,有时需要集群侧运维来进行调整。
1、 监控集群负载高的regionserver
HBase shell
status ‘detailed’
2、 迁移热点region至负载低的regionserver
确定了热点 Region 和负载高的 Region Server 后,我们可以将热点 Region 迁移至负载低的 Region Server 上,以实现负载均衡。
HBase shell
move 'region_name','target_region_server'
3、 监控负载均衡情况,并根据需要重复步骤1和2
最后,我们需要持续监控负载均衡情况,并根据需要重复执行步骤2和3。在迁移了热点 Region 后,集群的负载情况可能发生变化,可能出现新的热点 Region 或者负载高的 Region Server。因此,我们需要不断地进行监控和调整,以实现持续的负载均衡。