第 5 章 HBase 优化

5.1 RowKey 设计

一条数据的唯一标识就是 rowkey,那么这条数据存储于哪个分区,取决于 rowkey 处于哪个一个预分区的区间内,设计 rowkey的主要目的 ,就是让数据均匀的分布于所有的 region中,在一定程度上防止数据倾斜。接下来我们就谈一谈 rowkey 常用的设计方案。

  • 1)生成随机数、hash、散列值

  • 2)时间戳反转

  • 3)字符串拼接

需求:使用 hbase 存储下列数据,要求能够通过 hbase 的 API 读取数据完成两个统计需求。

(1)统计张三在 2021 年 12 月份消费的总金额

(2)统计所有人在 2021 年 12 月份消费的总金额

5.1.1 实现需求 1

为了能够统计张三在 2021 年 12 月份消费的总金额,我们需要用 scan 命令能够得到张三在这个月消费的所有记录,之后在进行累加即可。Scan 需要填写 startRow 和 stopRow:

       #**填充字段**保证所有数据有相同的长度
scan : startRow -> ^A^Azhangsan2021-12 
       #结尾需要写和设计的rowkey对应位置的值大的字符
       endRow -> ^A^Azhangsan2021-12.

注意点:

(1)避免扫描数据混乱,解决字段长度不一致的问题,可以使用相同阿斯卡码值的符号进行填充,框架底层填充使用的是阿斯卡码值为 1 的^A

(2)最后的日期结尾处需要使用阿斯卡码略大于’-’的值

最终得到 rowKey 的设计为:

//注意 rowkey 相同的数据会视为相同数据覆盖掉之前的版本
rowKey: ^A^Auserdate(yyyy-MM)(-dd HH:mm:SS)后面那截

5.1.2 实现需求 2

一种设计格式只能完美满足一个需求

scan:  startrow => 2021-12
       stoprow => 2021-12.

问题提出:按照需要 1 的 rowKey 设计,会发现对于需求 2,完全没有办法写 rowKey 的扫描范围。此处能够看出 hbase 设计 rowKey 使用的特点为:

适用性强 泛用性差 能够完美实现一个需求 但是不能同时完美实现多个需要。

如果想要同时完成两个需求,需要对 rowKey 出现字段的顺序进行调整。

调整的原则为:可枚举的放在前面。其中时间是可以枚举的,用户名称无法枚举,所以必须把时间放在前面。

最终满足 2 个需求的设计

可以**穷举**的写在前面即可
rowKey 设计格式 => date(yyyy-MM)^A^Auserdate(-dd hh:mm:ss ms)

(1)统计张三在 2021 年 12 月份消费的总金额
    scan: startRow => 2021-12^A^Azhangsan
          stopRow => 2021-12^A^Azhangsan.

(2)统计所有人在 2021 年 12 月份消费的总金额
    scan: startRow => 2021-12
          stopRow => 2021-12.

5.1.3 添加预分区优化

预分区的分区号同样需要遵守 rowKey 的 scan 原则。所有必须添加在 rowKey 的最前面,前缀为最简单的数字。同时使用 hash 算法将用户名月份拼接决定分区号。(单独使用用户名会造成单一用户所有数据存储在一个分区

添加预分区优化
startKey stopKey
         001
001      002
002      003
...
119      120

#       **用户+月份** 拼接到一起然后进行hash
分区号=> hash(user+date(MM)) % 120

分区号填充 如果得到 1 => 001

rowKey 设计格式 => 分区号 date(yyyy-MM)^A^Auserdate**(-dd hh:mm:ss ms)**

**缺点:**实现需求 2 的时候,由于每个分区都有 12 月份的数据,需要扫描 120 个分区。

解决方法:提前将分区号和月份进行对应。

提前将月份和分区号对应一下

000 到 009 分区 存储的都是 1 月份数据
010 到 019 分区 存储的都是 2 月份数据
...
110 到 119 分区 存储的都是 12 月份数据
是 9 月份的数据
分区号=> hash(user+date(MM)) % 10 + 80
分区号填充 如果得到 85 => 085
得到 12 月份所有人的数据
扫描 10 次
scan: startRow => 1102021-12
stopRow => 1102021-12.
...
startRow => 1122021-12
stopRow => 1122021-12.
..
startRow => 1192021-12
stopRow => 1192021-12.

5.2 参数优化

1)Zookeeper 会话超时时间

hbase-site.xml

属性:zookeeper.session.timeout
解释:默认值为 90000 毫秒(90s)。当某个 RegionServer 挂掉,90s 之后 Master 才能察觉到。
     可适当减小此值,尽可能快地检测 regionserver 故障,可调整至 20-30s。

看你能有都能忍耐超时,同时可以调整重试时间和重试次数
hbase.client.pause(默认值 100ms)
hbase.client.retries.number(默认 15 次)

2)设置 RPC 监听数量

hbase-site.xml

属性:hbase.regionserver.handler.count
解释:默认值为 30,用于指定 RPC 监听的数量,可以根据客户端的请求数进行调整,读写请求较多时,增加此值。

3)手动控制 Major Compaction

hbase-site.xml

属性:hbase.hregion.majorcompaction
解释:默认值:604800000 秒(7 天), Major Compaction 的周期,若关闭自动 MajorCompaction,
可将其设为 0。**如果关闭一定记得自己手动合并,因为大合并非常有意义**。

4)优化 HStore 文件大小

hbase-site.xml

属性:hbase.hregion.max.filesize
解释:默认值 10737418240(10GB),如果需要运行 HBase 的 MR 任务,可以减小此值,
因为一个 region 对应一个 map 任务,如果单个 region 过大,会导致 map 任务执行时间过长。
该值的意思就是,如果 HFile 的大小达到这个数值,则这个 region 会被切分为两个 Hfile。

5)优化 HBase 客户端缓存

hbase-site.xml

属性:hbase.client.write.buffer(不推荐改)
解释:默认值 2097152bytes(2M)用于指定 HBase 客户端缓存,增大该值可以减少 RPC调用次数,
但是会消耗更多内存,反之则反之。一般我们需要设定一定的缓存大小,以达到减少 RPC 次数的目的。

6)指定 scan.next 扫描 HBase 所获取的行数

hbase-site.xml

属性:hbase.client.scanner.caching
解释:用于指定 scan.next 方法获取的默认行数,值越大,消耗内存越大。

7)BlockCache 占用 RegionServer 堆内存的比例

hbase-site.xml

属性:hfile.block.cache.size
解释:默认 0.4,读请求比较多的情况下,可适当调大

8)MemStore 占用 RegionServer 堆内存的比例

hbase-site.xml

属性:hbase.regionserver.global.memstore.size
解释:默认 0.4,写请求较多的情况下,可适当调大

Lars Hofhansl(拉斯·霍夫汉斯)大神推荐 Region 设置 20G,刷写大小设置 128M,其它默认

5.3 JVM 调优

JVM 调优的思路有两部分:一是内存设置,二是垃圾回收器设置。

垃圾回收的修改是使用并发垃圾回收,默认 PO+PS 是并行垃圾回收,会有大量的暂停。理由是 HBsae 大量使用内存用于存储数据,容易遭遇数据洪峰造成 OOM,同时写缓存的数据是不能垃圾回收的,主要回收的就是读缓存,而读缓存垃圾回收不影响性能,所以最终设置的效果可以总结为:防患于未然,早洗早轻松。

1)设置使用 CMS 收集器:

-XX:+UseConcMarkSweepGC

2)保持新生代尽量小,同时尽早开启 GC,例如:

//在内存占用到 70%的时候开启 GC
-XX:CMSInitiatingOccupancyFraction=70
//指定使用 70%,不让 JVM 动态调整
-XX:+UseCMSInitiatingOccupancyOnly
//新生代内存设置为 512m
-Xmn512m

//并行执行新生代垃圾回收
-XX:+UseParNewGC
// 设 置 scanner 扫 描 结 果 占 用 内 存 大 小 , 在 hbase-site.xml 中,设置
hbase.client.scanner.max.result.size(默认值为 2M)为 eden 空间的 1/8(大概在 64M)

// 设置多个与 max.result.size * handler.count 相乘的结果小于 Survivor Space
(新生代经过垃圾回收之后存活的对象)

5.4 HBase 使用经验法则

官方给出了权威的使用法则:

  • (1)Region 大小控制 10-50G

  • (2)cell 大小不超过 10M(性能对应小于 100K 的值有优化),如果使用 mob(Mediumsized Objects 一种特殊用法)则不超过 50M。

  • (3)1 张表有 1 到 3 个列族,不要设计太多。最好就 1 个,如果使用多个尽量保证不会同时读取多个列族。

  • (4)1 到 2 个列族的表格,设计 50-100 个 Region。

  • (5)列族名称要尽量短,不要去模仿 RDBMS(关系型数据库)具有准确的名称和描述。

  • (6)如果 RowKey 设计时间在最前面,会导致有大量的旧数据存储在不活跃的 Region中,使用的时 候,仅仅会操作少数的活动 Region,此时建议增加更多的 Region 个数。

  • (7)如果只有一个列族用于写入数据,分配内存资源的时候可以做出调整,即写缓存不会占用太多的内存。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怕被各位卷死

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值