关于hbaseRegion和hbaseRowKey的一些处理

我遇到了什么问题?

我的habse一共有三台服务器,其中一台忙的要死,另外两台吃瓜看戏,我的业务都在其中一个服务器上,导致数据的读写瓶颈。

先说一下hbase的概况,有一个整体了解,我们再讲原因。

长话短说,hbase是列簇存储, 查询的时候需要根据rowkey进行数据的K-V检索。

为了管理数据,hbase构建了region记录当前region存储的rowkey的范围,及真实数据。

为了支持分布式,一个表会存在多个region,分布在不同的机器。

概况有了,讲一下我遇到的问题。

我司三台服务器,三条频繁使用hbase的业务线,平均一条业务线一台机器,虽然公司抠抠索索,但是这个资源也基本够用了啊!怎么导致数据写入瓶颈了呢?而且是突然不行了?

  1. 首先内部排查,突然不行了,是不是后台发版导致的。比如:上线了redis的keys,会把redis搞蹦,hbase是不是上线了类似的容易导致异常的指令。
  2. 再排查,仅仅是我的服务不行还是大家试用hbase的都不行,自己不行就先自己找原因。大家都不行就外部找原因。
  3. 外部排查,是不是服务器不行?比如:物理的宿主机异常。检测之后正常。
  4. 细节上排查,为什么慢,找到一个请求,看看服务器在干啥?服务器在进行fullGC,能否开启并行GC,(上次异常是fullGC的原因,已经开启了并行gc稳定运行了将近3年。)
  5. 根据服务器特性分析,一个服务器繁忙,两外两个服务器空闲,查看分析一下服务器的cpu使用差异。
    异常后的三个节点cpu使用:4:1:1。整体百分之60的压力给到了一个服务器。超出了设计的用量一倍。崩了,真的不稀奇。为啥流量差异这么大呢?继续定位。
    先看一下我的这个表的region数据,根据请求量排序查看。数量级是4百万,往下拖一下后面的数量级才4千,差了一千倍。而且恰恰这两个region,都恰好在我的繁忙机器上。

    真相破案了。
    三条业务线的数据读写请求都集中在最近的几个region,当这几个region都集中在一台服务器上的时候,像级了三体描述的三日凌空。我的服务器瘫了,瘫了,了。
    请求集中到最近几个region这是病,要治, 刚好我有药,需要的划到底下。

问题定位到了,开始分析产生原因(不感兴趣的可以跳过,不影响后续阅读)

  1. habse怎么管理这些rowkey?
    hbase系统内部给了一个管理rowkey的东西. 它就是我们本期说的region.
    region存储了什么? 一张表对应多个region(详见:list_regions),region存储了自己所在的serverName节点信息. 存储了rowkey的startKey和endKey
    这个范围内的rowkey都会经过这个region统一进行调配.去哪个节点位置查数据, 去哪个节点位置改数据.
    哦,原来请求到达,我们要先根据rowkey去region列表(去匹配startkey和endKey)检索的数据所在region信息(详见:locate_region)。
    再去region对应的服务器,检索当前rowkey对应的文件存储信息。再去各个节点读取数据。
  2. region为什么会创建多个?
    每个region会对应一个具体的server服务器来帮助查询rowkey对应的文件信息。
    如果单个region那么压力都积压到一个server服务器了,没有充分利用起来分布式的优点 。
  3. region是需要我们手动创建拆分指定,还是自动指定?
    hbase的内置策略,当数据量超过阈值(10GB),会自动进行当前的region拆分。拆分为两个,这个过程资源消耗比较大。
    可以通过预生成的方式进行region的生成(有些场景有必要,有些场景没有必要)。
    比如0-100,再填充101的时候发现过大要拆分了,0-100拆分成了0-80, 80-160. 那么我们在创建region的时候就可以直接创建0-80,80-160.
    现在我们同一个表的不同rowkey查询的时候走不同的region, 不同的region可能分布在不同的server服务器。 nice。
  4. 为什么运行过程中为什么单个节点负载高,其它节点负载低?
    很多情况下rowkey设计不合理导致的。(嗯,我们现在就是直接copy了自增业务主键)。数据不断写,region到达顶峰,不断拆分。但是业务的增删改查,大部分都是发生在近期的数据。这就导致热数据比较集中。你会发现这会热数据的region在1号服务器,1号服务器忙的要死,其余服务器全在吃瓜看戏。一个表这样还好些,压力能扛住,但是当核心的3-5个服务的热数据同时在1号节点的时候,灾难真的来临了。

原因找到了,看一下改正方案吧!

RowKey的三大设计原则

region能不能均衡分布。取决于rowkey.

1、散列原则,不要用类似于时间戳这样的不断增大的数据直接作为RowKey,如果确实需要用时间戳,可以把它放在低位,高位用散列来占位。

2、长度原则,其实总结就一句话,rowkey只是一个唯一标识符,并没有更多的实际意义,所以不要搞得太长(16字节),

3、唯一性原则,这一点没什么好说的,RowKey需要唯一确定一条数据,所以必须唯一。

咱们说一下散列的常用方式。常见的有hash(md5生成)/加盐(加用户id等)/反转(逆序)

个人推荐用逆序,好处及具体实现方式见后附。

rowkey的散列处理方式反转具体如何做

在网上看了一下大神们的反转策略,感觉和我的业务场景不太一样。

我现在的方案是反转,然后末尾补0,到我的预测数量级比如我预测数量级是最大百亿数据,那么我补0补齐至10位。

优点: 当数量级跃迁时,不会产生数据倾斜(热数据集中)

缺点:rowKey的长度比常规更大,占用更多资源。

我现在的反转方案是这样的。

1 反转为 1000000000(1后补0至10位)

2 反转为 2000000000(5后补0至10位)

5 反转为 5000000000(5后补0至10位)

10 反转为 0100000000(01后补0至10位)

50 反转为 0500000000(05后补0至10位)

100 反转为 0010000000(001后补0至10位)

500 反转为 0050000000(005后补0至10位)

1000反转为 0001000000(0001后补0至10位)

5000反转为 0005000000(0005后补0至10位)

正常反转之后末尾补0凑够指定位数。(rowkey的长度可能比较长)。

只要没有超过我们的预期数据量,那么这个rowkey在哪个位置就由原始数据的末尾几位决定的(反转之后成为了首位)。如果拆了10个region.

结尾为1的落在了1000000-2000000区间,结尾为2 的落在了2000000-3000000区间。。。。

数量级从十万级别升级到了百万级别。热数据还是根据结尾的值均匀分布。

如果随着时间的增加,新数据来了,老数据走了。来的数据末位数有1有2,走的数据末位数有1有2.

基本能保持平衡,很难会出现某些region里面没有数据的情况。

为什么数据跃迁之后不补零会导致热点数据集中。

假如跃迁之前我的数据量级是不足百万,99万的数据拆分了99个region(1万一个)。

产生第1000001数据时反转=1000001 比百万数据多了一个量级。

原始数量为123456位,最新的为1234567位。

1000002--->2000001

1000003-->3000001

1000004-->4000001

1001004-->4001001

1百万之后的数据都会分配到。起止点最大的region, 并且已有的其他region,因为数量级较小,不会被分配新的数据,热点数据集中在某几个region,发生了数据倾斜。

即便后续新节点拆分,那么热数据也是集中在新拆分的几个节点里面,前面的99个节点基本被废弃了。

我们数据不单单填充啊!还是存在删除的情况。但是数据删除之后即便region里面没有数据了,region的这个拆分还是依然保留的。如果随着时间的增加,新数据来了,老数据走了,前面的这个99个region里面没有数据了,但是region依然存在。

指标不治本的临时解决方案。

你说"我现在服务器都崩了,你给我讲rowkey怎么改,改完规则,测试,上线。3天出去了。咋整?"

不慌哈!指标不治本的解决方案咱也有。

现在数据倾斜,热点数据集中到某几个region,我们把他迁移走不就成了吗?

hbase 有一个move指令,迁移region到其它的服务器,可以指定服务器,也可以让hbase根据自己的规则选择最优服务器。

encodedRegionName 是region名称的hash后缀。 如果region名称是:TestTable,0094429456,1289497600452.527db22f95c8a9e0116f0cc13c680396. 那么endodeedRegionName是527db22f95c8a9e0116f0cc13c680396

我们的命令就是

move '527db22f95c8a9e0116f0cc13c680396'

热点的region移动出去,服务的cpu就降下来了。

根治方法

更改rowkey的生成规则, 如果是因为rowkey生成规则不合适导致的热点数据集中的数据倾斜,就需要更改rowKey的生成规则(强推逆序简单可靠), 更改rowKey的生成规则后记得同时更改,读和写,并且要考虑历史已经写入数据的兼容性。

  1. 考虑新的规则写入数据是否和历史数据重合。
  2. 程序如何能设置分割线,同时读取新的规则写入的key和老的规则写入的key。

其他问题。

hbase的region会自动删除吗?

有些业务可能只保留近期几年的数据,hbase可以通过ttl来进行设置。hbase内置的检索规则会最终删除这些数据。如果一个region内部对应的rowkey数据都删除了, 我的region会自动删除吗?不会!

我们前面也讲过,region可以进行预生成。都能预生成了。预生成的就是没有对应数据的region.所以系统上是默认支持这样的。 我的数据不断存储,不断ttl删除,region也不断增大,有什么解决方案吗?使用现有的命令行进行merge(详见merge_region)

查看单个表的region信息

复制代码
help list_regions
hbase> list_regions 'table_name'
hbase> list_regions 'table_name', 'server_name'
hbase> list_regions 'table_name', {SERVER_NAME => 'server_name', LOCALITY_THRESHOLD => 0.8}
hbase> list_regions 'table_name', {SERVER_NAME => 'server_name', LOCALITY_THRESHOLD => 0.8}, ['SERVER_NAME']
hbase> list_regions 'table_name', {}, ['SERVER_NAME', 'start_key']
hbase> list_regions 'table_name', '', ['SERVER_NAME', 'start_key']
相关推荐
扶风呀2 天前
具有熔断能力和活性探测的服务负载均衡解决方案
运维·负载均衡
Hello World呀2 天前
springcloud负载均衡测试类
spring·spring cloud·负载均衡
菜菜子爱学习3 天前
Nginx学习笔记(七)——Nginx负载均衡
笔记·学习·nginx·负载均衡·运维开发
扶风呀3 天前
负载均衡详解
运维·后端·微服务·面试·负载均衡
PXM的算法星球3 天前
spring gateway配合nacos实现负载均衡
spring·gateway·负载均衡
抛物线.6 天前
Docker Compose 部署高可用 MongoDB 副本集集群(含 Keepalived + HAProxy 负载均衡)
mongodb·docker·负载均衡
ZNineSun7 天前
什么是负载均衡,有哪些常见算法?
负载均衡·osi·七层网络模型
竹竿袅袅7 天前
Nginx 反向代理与负载均衡架构
nginx·架构·负载均衡
lifallen8 天前
HBase的异步WAL性能优化:RingBuffer的奥秘
大数据·数据库·分布式·算法·性能优化·apache·hbase
运维行者_8 天前
多数据中心运维:别让 “分布式” 变成 “混乱式”
运维·数据库·分布式·测试工具·自动化·负载均衡·故障告警