升级背景
个推作为专业的数据智能服务商,在业务开展过程中存在海量的数据存储与查询的需求,为此个推选用了高可靠、高性能、面向列、可伸缩的分布式数据存储系统——HBase。
然而,运行 HBase 老集群(使用 HBase1.0 版本)多年后,遇到了两大问题:各节点基础环境不一致;该集群的服务器运行多年已过保。而且随着个推业务量增长,性能方面也开始遇到瓶颈。经过综合评估,个推决定将老集群升级并迁移到 HBase2.0 新集群以解决 HBase 老集群存在的上述问题。
升级步骤
下面是个推升级并迁移的全步骤,供开发者参考。由于整个过程将涉及多个部门且用时长,建议各位在操作的过程中可以让各部门指定专人对接。
准备 1:HBase 表认领,找到所有表的读写应用与业务方;
准备 2:HBase2.0 新集群部署,并打通到所有读写应用服务器的网络;
调试 3:测试环境调试应用,确认能正常使用 HBase2.0 集群;
调试 4:开发数据校验工具,对迁移后新老集群数据进行完整性校验;
迁移 5:所有表双写工程上线,并确认新老集群写入数据一致;
迁移 6:所有读取应用变更,迁移到新集群,确认读取正常;
收尾 7:老集群写入工程停止,表禁用半个月,无异常后老集群下线。
HBase2.0 新特性
2018 年 4 月 29 日,HBase2.0 发布,共包含了 4551 个 Issues。HBase2.0 的新特性非常多,本次只介绍主要的几个特性,更多内容见官网文档。
[https://issues.apache.org/jir…]
特性 1:AssignmentManager V2
AMv1 存在的问题及原因分析
AMV1 存在的主要问题是 Regoins in Transition(RIT)。深度使用 HBase 的人一般都被 RIT 困扰过,长时间的 RIT 简直令人抓狂。一些 RIT 确实是由于 Region 无法被 RegionServer open 造成的,但大部分的 RIT,都是 AM 本身的问题引起的。
引发 RIT 的原因主要有以下几点:
- Region 状态变化复杂
Region open 的过程有 7 个组件参与并涉及 20 多个步骤,但越复杂的逻辑意味着越容易出 bug。
2.region 状态多处缓存
Master 内存、Meta 表、Zookeeper 都会保存 region 的状态,Hbase1.0 要求三者要保持完全同步;
Master 和 RegionServer 都会修改 Meta 表的状态和 Zookeeper 的状态,这将非常容易导致 region 状态出现混乱;
如果出现不一致,到底以哪里的状态为准?
3. 严重依赖 Zookeeper 进行状态通知
Region 状态的通知完全通过 Zookeeper,这导致了 region 的上线 / 下线的速度存在着一定的瓶颈。特别是在 region 比较多的时候,Zookeeper 的通知会出现严重的滞后现象。
AMv2 的改进
主要的改进有以下四点:
1.region 每次状态变化,会先记录到 ProcedureWAL 中,然后记录在 Meta 表;
2.region 状态信息只存放两个地方:meta 表、HMaster 的内存,不再存放 Zookeeper;
3. 只有 HMaster 才可以更新 meta 表中的信息;
4.HMaster 与 RS 直接进行状态信息同步,去除 Zookeeper 依赖;
整体上来看,AMv2 去除了 Zookeeper 依赖,有清晰明了的 region transition 机制,代码的可读性更强,非常有效地解决了 RIT 现象。
特性 2:In-memory Flush & Compaction
HBase 写入流程中,数据会先写入 Memstore(内存中),达到阈值后,会触发 flush 刷新,生成 HFile 文件落到磁盘中。需要注意的是 MemStore 的最小 flush 单元是‘HRegion’而不是单个 MemStore,如果 HRegion 中 Memstore 过多,每次 flush 的 IO 开销会很大。
HBase1.x 的问题
Memstore flush 刷新的触发条件很多,不过大多数对业务影响小,开发者无需担心。但如果触发 Region Server 级别 flush,将会导致整个 RS 执行 flush,阻塞所有落在该 Region Server 上的更新操作,而且阻塞时间很长,可能会达到分钟级别,对业务影响非常大。
HBase2.0 的改进
在 2.0 版本中,MemStore 中的数据先 Flush 成一个 Immutable 的 Segment,多个 Immutable Segments 可以在内存中进行 Compaction,当达到一定阈值以后才将内存中的数据持久化成 HDFS 中的 HFile 文件。这就是 2.0 的新特性:In-memory Flush and Compaction,而且该特性在 2.0 版本中已被默认启用(系统表除外)。
好处 1:减少数据量、降低磁盘 IO,很多表的列簇只保留 1 个版本;
好处 2:Segment 来替代 ConcurrentSkipListMap 数据结构存储索引,节省空间,同样的 MemStore 可以存储更多的数据。
特性 3:Offheaping of Read/Write Path
HBase 服务读写数据较多依赖堆内内存实现,JVM 采用的是 stop-the-world 的方式进行垃圾回收,很容易造成 JVM 进程因为 GC 而停顿时间比较长。而 HBase 是一个低延迟、对响应性要求比较高的系统,GC 很容易造成 HBase 服务抖动、延迟高。
HBase 社区解决 GC 延迟的思路是尽量减少使用 JVM 堆内内存,堆内内存使用减少了,GC 也就随着减少了,社区为此支持了读写链路的 offheap。
读链路的 offheap 主要包括以下几个优化:
- 对 BucketCache 引用计数,避免读取时的拷贝;
- 使用 ByteBuffer 做为服务端 KeyValue 的实现,从而使 KeyValue 可以存储在 offheap 的内存中;
- 对 BucketCache 进行了一系列性能优化。
写链路的 offheap 包括以下几个优化:
- 在 RPC 层直接把网络流上的 KeyValue 读入 offheap 的 bytebuffer 中;
- 使用 offheap 的 MSLAB pool;
- 使用支持 offheap 的 Protobuf 版本(3.0+)。
HBase2.0 的“坑”
V2.0.3 之前版本不支持 HBCK2
<pre>
HBCK2 versions should be able to work across multiple hbase-2 releases. It will fail with a complaint if it is unable to run. There is no HbckService in versions of hbase before 2.0.3 and 2.1.1. HBCK2 will not work against these versions.
</pre>
建议 HBase 升级到 V2.0.3 或 V2.1.1,详情看 HBCK2 文档。
[https://github.com/apache/hba…]
重度依赖 Procedure V2
AMv2 之所以能保持简洁高效的一个重要原因就是其重度依赖了 Procedure V2,把一些复杂的逻辑都转移到了 Procedure V2 中。但是这样做的问题是:一旦 ProcedureWAL 出现了损坏,这个后果就是灾难性的。当然,小编相信经过一段时间的 bug 修复和完善后,这些问题将不复存在。
HBase 作为个推大数据一项重要的基础服务,性能的好坏影响重大。个推将 HBase1.0 升级到了 HBase2.0 版本后,在可靠性、安全性方面都有了很大提升,有效解决了 1.0 版本中的多种问题。未来,个推将会持续关注 HBase 2.0,与大家共同探讨如何在生产环境中更好地对其进行使用。