问题发现
年前数据中台新接入了一张表,监控日志发现,该表 hive ods 表映射过程中,占用的资源非常之大,可以说剩余多少资源,它就能吃掉所有资源,以至于同时段运行的任务全部失败,我是非常的闹心呀。
问题定位
自己左分析右分析,也没弄出个123出来,便请教了一下同事。同事分析后,问我 hbase 建表的时候有没有进行 预分区
,啥玩意?这完全超出了我的知识边界,(小声逼逼:够水的。。。)。
果不其然,在 hbase 控制台 192.168.0.101:60010/tablesDetailed.jsp
看到,这个表仅用到了一个 Region Server,而数据量非常大(我查了下一共两亿多条),这么大的数据量只用一台服务器处理,集群的优势丝毫没能体现,怪不得这么慢。
hbase 预分区
hbase 基本介绍
hbase 表创建时,默认分配某个 region server 的一个 region,所有的写入的查询都是操作的这个 region ,数据量小的时候没用什么问题,数据量达到一定程度时(一般是 10G),会进行分裂 split,这种分裂也只是新增一个 region ,如此一来,集群中的其他 region server 就会处于一个比较闲的状态,集群就达不到负载均衡的效果了。这就是预分区特性的由来。
预分区可以有如下几个有点:
- 提供数据操作效率(读和写);
- 使得集群处于负载均衡的状态,防止数据倾斜;
- 便于容灾调度 region;
- 优化 map 数量
hbase 预分区设计及制定
hbase 预分区一般采用 2 位数字前缀,即:10,20,30,40,50,60,70,80,90,(第一个分区没用 Start Key,最后一个分区没用 End Key,所以是 10 个分区)。
设置命令如下:
也可以使用 16 进制序列设置预分区。
设置命令如下:
此时,其预分区是 11111111 ~ ffffffff,(第一个分区没用 Start Key,最后一个分区没用 End Key,所以是 16 个分区)。
需要特别注意的是预分区的设计和 hbase rowkey 的设计紧密相关,因为良好的 rowkey 设计能够确保数据能够均匀的命中不同的 region ,从而避免 数据写入热点
的产生,实现写请求的负载均衡。
仔细观察问题表的 rowkey,其前缀是日期的反转,某个日期的数据会落地到相同的 region,这显然是不合理,因为总是写入一个 region,经过分析,将 rowkey 前缀调整为数据接入时间戳的反转,反转之后,rowkey 的前缀是均匀分布的,完美解决了之前的问题。
问题处理
确定问题之后,就可以进行对症处理了,这个问题的根本原因是 hbase 表未设置预分区且 rowkey 设计不合理,两个问题一并处理,hbase 设置预分区需要重建表,rowkey 需要修改代码,重新部署程序,经过梳理,问题处理步骤如下:
- 删除 hive middle 库中的对应表
- 停止 student 数据接入相关程序(先停程序再操作 hbase 表)
- 由于想保留 hbase 表数据,所以要将其数据进行备份(通过快照实现)
需要特别注意的是:快照操作过程中,不能填写命名空间,否则会报错。
- 重建 hbase 表
- 修改 student 数据接入程序中的 rowkey 设计,前缀调整为数据接入时间戳反转,并重新进行打包、部署及上线。
- 查看 student 数据接入情况是否正常。
- hbase 控制台查看 Region Server 情况,发现其 region server 由一个变为多个。
- 重启执行 hive ods 表映射 shell,占用资源明细减少,操作时间明显缩短,问题解决。
问题总结
hbase 预分区可以说是我的知识盲区(不知道自己不知道的知识),要学习的内容还是由很多呀,加油干吧,小伙子。