searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

HBase热点问题和规避策略

2024-05-31 05:34:32
17
0

在HBase 中,数据热点问题指的是某些Region Server 处理的数据集中在少数几个 Region 中,导致这些 Region Server 负载过高,而其他 Region Server 的资源却没有得到充分利用。这种情况下,会导致性能下降和系统不稳定。为了解决这个问题,我们需要将数据负载平衡,确保每个 Region Server 能够均衡处理请求。

用户侧策略:

建议应用侧优化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 - 结束时间] ,这样范围查询的性能也不受影响。

  1. 预分区

Hbase中的表会被划分为n个Region,然后存放在多个RegionServer中,每个Region有StartKey和EndKey,表示这个Region维护的RowKey范围,而第一个Region没有StartKey,最后一个Region没有EndKey。需要读写数据时,RowKey会落在某个范围内,就会定位到目标的Region以及所在的RegionServer。

假如应用的表有10个分区,每个分区的最大大小为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’
image.png

  1. 迁移热点region至负载低的regionserver

确定了热点 Region 和负载高的 Region Server 后,可以将热点 Region 迁移至负载低的 Region Server 上,以实现负载均衡。

HBase shell

move 'region_name','target_region_server'

  1. 监控负载均衡情况,并根据需要重复步骤1和2

最后,需要持续监控负载均衡情况,并根据需要重复执行步骤2和3。在迁移了热点 Region 后,集群的负载情况可能发生变化,可能出现新的热点 Region 或者负载高的 Region Server。因此,需要不断地进行监控和调整,以实现持续的负载均衡。

0条评论
0 / 1000
c****x
3文章数
0粉丝数
c****x
3 文章 | 0 粉丝
c****x
3文章数
0粉丝数
c****x
3 文章 | 0 粉丝
原创

HBase热点问题和规避策略

2024-05-31 05:34:32
17
0

在HBase 中,数据热点问题指的是某些Region Server 处理的数据集中在少数几个 Region 中,导致这些 Region Server 负载过高,而其他 Region Server 的资源却没有得到充分利用。这种情况下,会导致性能下降和系统不稳定。为了解决这个问题,我们需要将数据负载平衡,确保每个 Region Server 能够均衡处理请求。

用户侧策略:

建议应用侧优化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 - 结束时间] ,这样范围查询的性能也不受影响。

  1. 预分区

Hbase中的表会被划分为n个Region,然后存放在多个RegionServer中,每个Region有StartKey和EndKey,表示这个Region维护的RowKey范围,而第一个Region没有StartKey,最后一个Region没有EndKey。需要读写数据时,RowKey会落在某个范围内,就会定位到目标的Region以及所在的RegionServer。

假如应用的表有10个分区,每个分区的最大大小为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’
image.png

  1. 迁移热点region至负载低的regionserver

确定了热点 Region 和负载高的 Region Server 后,可以将热点 Region 迁移至负载低的 Region Server 上,以实现负载均衡。

HBase shell

move 'region_name','target_region_server'

  1. 监控负载均衡情况,并根据需要重复步骤1和2

最后,需要持续监控负载均衡情况,并根据需要重复执行步骤2和3。在迁移了热点 Region 后,集群的负载情况可能发生变化,可能出现新的热点 Region 或者负载高的 Region Server。因此,需要不断地进行监控和调整,以实现持续的负载均衡。

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0