作死系列之论如何搞崩生产环境HBASE

结果描述

  • HBASE集群被搞垮一台机器
  • 集群的平响有 40ms 左右 暴增至 40s 左右

需求背景

  • 当前有两天条数据流 A 与 B , 消息管道均为 Kafka , 其中, A 数据流中存有行为的 开始与结束信息 , B 数据流中存有在生命周期期之内m, 离散的行为数据 .
  • 需要将 A 与 B两个管道的数据合并为一条数据, 同时要将 B 中的离散行为数据合并为一条完整的,合并完成的数据, 写入 hbase.
  • 数据大小 : A管道数据1条, 大小 2kb , B管道 单条数据 0.1kb , 但是数量多, 45条/s , 一个生命周期大约 500条 数据, 数据大小 500 * 0.1 = 50 kb.

方案设计

  • 使用hbase多列存储数据, data_a 列, 存储 A 数据管道的数据, data_b 列存储数据管道 B 的数据
  • B 管道中的数据, 每订阅到一条 , 使用HBase原生支持的 append 方法, 将数据追加到末尾, 从而达到 将离散数据合并的目的 .

服务上线

按照如上方案, 进行实现之后, 进行上线. 上线之后, 大约半小时左右, 负责 HBase 同学电话报警, 集群平响异常拉高 , 且有 一台机器发生宕机 . 还好我们溜了后手, 从配置中心关闭了对HBase的数据使用, 快速止损.

问题定位

上述方案听起来没啥问题, 技术和业务都没啥问题的样子, 但是为什么上线之后, 会产生这么糙单的问题呢? 这里忽略了一个问题, 也是HBase核心特性之一 : 数据的多版本存储 , 是不是有点想到了什么? 没错, 每次 append 都会生成一个新的数据版本, append 多少次, 就有多少数据版本.

现在依旧假设一个生命周期内, 会产生 500 条离散数据, 那我们来计算一下, 这些数据的大小 :

  • 首先, 500 条数据, 就会产生 500 个数据版本, 每一个版本的数据大小 = 前一个数据版本大小 + 单条数据大小
  • 数据总条数计算规则 : 1 + (1+2) + (1+2+3) + (1+2+3+….+500) = 20958500 条数据, 大小为 : 20958500 * 0.1 = 2095850 kb, 约为 2046M, 2GB左右
  • 业务系统有配置重试, 当写 HBase 超时时, 会重试一次, 假定重试概率为 10%, 那实际写入的数据应给是 500 * (1 + 10%) = 550 , 按照上面的规则重新计算, 数据大小 27880600 kb 约为 2723MB , 2.5GB左右.

怎么样, 数据是不是比想象中的大太多了, 明明预期不过 50kb 左右, 它咋就膨胀到 2.5GB 了, 数据量可是 膨胀5W倍 , 夭寿啊!

方案再设计

  • 将 append 操作变更为 put 操作 , 数据量相同的情况下, put 与 append QPS 相同, 但是会 节省大量存储空间
  • 离散的数据 rowKey 为 : 公共前缀_纳秒时间戳 , 不同生命周期的数据, 公共前缀(基于业务生成)不相同
  • 当订阅到 A 管道中生命周期结束的事件消息, 通过 HBase 的 Scan扫描命令 , 扫描数据, 合并后存入 data_b 列
  • 注意, 以为能匹配到公共的前缀, 此处 Scan 命令的性能是有保障的, 可以不用担心.

复盘

为什么在生产环境会导致这个问题?

  • 测试环境没有足够的数据, 没做大数据量的数据测试, 而基于 append 的实现, 从业务而言是没问题的, 所以没发现
  • 对 HBase 理解程度不足, 方案设计不够谨慎.

那是不是永远不要使用Append命令?非也.因为一次故障就彻底否定一个方案, 全权是一种因噎废食的行为, 只要在使用前充分评估好 数据量 以及 数据大小 等, 完全可以放心使用.

总结

当一个服务涉及到自己不熟悉的技术时, 一定要做到 充足 的技术调研, 但是由于不熟悉, 我们自身所理解的 充足调研 时远不充分的, 所以要有 配套的降级方案 , 当出现异常时, 可以及时止损.

每天上一当, 当当不一样! 感谢阅读!


作死系列之论如何搞崩生产环境HBASE
http://www.zhangdeman.cn/archives/57d96b27.html
作者
白茶清欢
发布于
2021年4月24日
许可协议