写点什么

Apache HBase MTTR 优化实践:减少恢复时长

发布于: 2 小时前

摘要:HBase 是 Hadoop Database 的简称,是建立在 Hadoop 文件系统之上的分布式面向列的数据库,它具有高可靠、高性能、面向列和可伸缩的特性,提供快速随机访问海量数据能力。


本文分享自华为云社区《Apache HBase MTTR优化实践》,作者: pippo。

 

HBase 是 Hadoop Database 的简称,是建立在 Hadoop 文件系统之上的分布式面向列的数据库,它具有高可靠、高性能、面向列和可伸缩的特性,提供快速随机访问海量数据能力。


HBase 采用 Master/Slave 架构,由 HMaster 节点、RegionServer 节点、ZooKeeper 集群组成,底层数据存储在 HDFS 上。


整体架构如图所示:



HMaster 主要负责:

  • 在 HA 模式下,包含主用 Master 和备用 Master。

  • 主用 Master:负责 HBase 中 RegionServer 的管理,包括表的增删改查;RegionServer 的负载均衡,Region 分布调整;Region 分裂以及分裂后的 Region 分配;RegionServer 失效后的 Region 迁移等。

  • 备用 Master:当主用 Master 故障时,备用 Master 将取代主用 Master 对外提供服务。故障恢复后,原主用 Master 降为备用。


RegionServer 主要负责:

  • 存放和管理本地 HRegion。

  • RegionServer 负责提供表数据读写等服务,是 HBase 的数据处理和计算单元,直接与 Client 交互。

  • RegionServer 一般与 HDFS 集群的 DataNode 部署在一起,实现数据的存储功能。读写 HDFS,管理 Table 中的数据。


ZooKeeper 集群主要负责:

  • 存放整个 HBase 集群的元数据以及集群的状态信息。

  • 实现 HMaster 主从节点的 Failover。


HDFS 集群主要负责:

  • HDFS 为 HBase 提供高可靠的文件存储服务,HBase 的数据全部存储在 HDFS 中。


结构说明:


Store

  • 一个 Region 由一个或多个 Store 组成,每个 Store 对应图中的一个 Column Family。


MemStore

  • 一个 Store 包含一个 MemStore,MemStore 缓存客户端向 Region 插入的数据,当 RegionServer 中的 MemStore 大小达到配置的容量上限时,RegionServer 会将 MemStore 中的数据“flush”到 HDFS 中。


StoreFile

  • MemStore 的数据 flush 到 HDFS 后成为 StoreFile,随着数据的插入,一个 Store 会产生多个 StoreFile,当 StoreFile 的个数达到配置的阈值时,RegionServer 会将多个 StoreFile 合并为一个大的 StoreFile。


HFile

  • HFile 定义了 StoreFile 在文件系统中的存储格式,它是当前 HBase 系统中 StoreFile 的具体实现。


HLog(WAL)

  • HLog 日志保证了当 RegionServer 故障的情况下用户写入的数据不丢失,RegionServer 的多个 Region 共享一个相同的 HLog。


HBase 提供两种 API 来写入数据。

  • Put:数据直接发送给 RegionServer。

  • BulkLoad:直接将 HFile 加载到表存储路径。

​ 

HBase 为了保证数据可靠性,使用 WAL(WriteAhead Log)来保证数据可靠性。它是 HDFS 上的一个文件,记录 HBase 中数据的所有更改。所有的写操作都会先保证将数据写入这个文件后,才会真正更新 MemStore,最后写入 HFile 中。如果写 WAL 文件失败,则操作会失败。在正常情况下,不需要读取 WAL 文件,因为数据会从 MemStore 中持久化为 HFile 文件。但是如果 RegionServer 在持久化 MemStore 之前崩溃或者不可用,系统仍然可以从 WAL 文件中读取数据,回放所有操作,从而保证数据不丢失。


写入流程如图所示:



默认情况下 RegionServer 上管理的所有 HRegion 共享同一个 WAL 文件。WAL 文件中每个记录都包括相关 Region 的信息。当打开 Region 时,需要回放 WAL 文件中属于该 Region 的记录信息。因此,WAL 文件中的记录信息必须按 Region 进行分组,以便可以回放特定 Region 的记录。按 Region 分组 WAL 的过程称为 WAL Split。

​ 

WAL Split 由 HMaster 在集群启动时完成或者在 RegionServer 关闭时由 ServershutdownHandler 完成。在给定的 Region 再次可用之前,需要恢复和回放所有的 WAL 文件。因此在数据恢复之前,对应的 Region 无法对外服务。


HBase 启动时,Region 分配简要分配流程如下:

  • HMaster 启动时初始化 AssignmentManager。

  • AssignmentManager 通过 hbase:meta 表查看当前 Region 分配信息。

  • 如果 Region 分配依然有效(Region 所在 RegionServer 依然在线),则保留分配信息。

  • 如果 Region 分配无效,调用 LoadBalancer 来进行重分配。

  • 分配完成后更新 hbase:meta 表。


本文主要关注集群重新启动和恢复相关内容,着重描述相关优化,减少 HBase 恢复时长。

RegionServer 故障恢复流程


当 HMaster 检测到故障时,会触发 SCP(Server Crash Procedure)流程。SCP 流程包括以下主要步骤:

  • HMaster 创建 WAL Split 任务,用于对属于崩溃 RegionServer 上 Region 进行记录分组。

  • 将原属于崩溃 RegionServer 上 Region 进行重分配,分配给正常 RegionServer。

  • 正常 RegionServer 执行 Region 上线操作,对需要恢复数据进行回放。



故障恢复常见问题

HMaster 等待 Namespace 表超时终止


当集群进行重启时,HMaster 进行初始化会找到所有的异常 RegionServer(Dead RegionServer)并开始 SCP 流程,并继续初始化 Namespace 表。


如果 SCP 列表中存在大量的 RegionServer,那么 Namespace 表的分配将可能被延迟并超过配置的超时时间(默认 5 分钟),而这种情况在大集群场景下是最常见的。为临时解决该问题,常常将默认值改大,但是必不能保证一定会成功。



另外一种方式是在 HMaster 上启用表来避免此问题(hbase.balancer.tablesOnMaster=hbase:namespace),HMaster 会优先将这些表进行分配。但是如果配置了其它表也可以分配到 HMaster 或者由于 HMaster 性能问题,这将无法做到 100%解决此问题。此外在 HBase 2.X 版本中也不推荐使用 HMaster 来启用表。解决这个问题的最佳方法是支持优先表和优先节点,当 HMaster 触发 SCP 流程时,优先将这些表分配到优先节点上,确保分配的优先级,从而完全消除此问题。

批量分配时 RPC 超时


HBase 专门线性可扩展性而设计。如果集群中的数据随着表增加而增多,集群可以很容易扩展添加 RegionServer 来管理表和数据。例如:如果一个集群从 10 个 RegionServer 扩展到 20 个 RegionServer,它在存储和处理能力方面将会增加。


随着 RegionServer 上 Region 数量的增加,批量分配 RPC 调用将会出现超时(默认 60 秒)。这将导致重新进行分配并最终对分配上线时间产生严重影响。


在 10 个 RegionServer 节点和 20 个 RegionServer 节点的测试中,RPC 调用分别花费了约 60 秒和 116 秒。对于更大的集群来说,批量分配无法一次成功。主要原因在于对 ZooKeeper 进行大量的读写操作和 RPC 调用,用来创建 OFFLINE ZNode 节点,创建正在恢复的 Region ZNode 节点信息等。

恢复可扩展性测试


在 10 到 100 个节点的集群测试中,我们观察到恢复时间随着集群规模的增大而线性增加。这意味着集群越大,恢复所需的时间就越多。特别是当要恢复 WAL 文件时,恢复时间将会非常大。在 100 个节点的集群中,通过 Put 请求写入数据的情况下,恢复需要进行 WAL Split 操作,发现需要 100 分钟才能从集群崩溃中完全恢复。而在相同规模的集群中,如果不写入任何数据大约需要 15 分钟。这意味着 85%以上的时间用于 WAL Split 操作和回放用于恢复。




下面我们将分析测试过程中发现的瓶颈在哪里?

恢复耗时分析

HDFS 负载


在 10 个节点的 HBase 集群上,通过 JMX 来获取 HDFS 的 RPC 请求监控信息,发现在启动阶段有 1200 万读取 RPC 调用。


其中 GetBlockLocationNumOps:380 万、GetListingNumOps:13 万、GetFileInfoNumOps:840 万。


当集群规模达到 100 个时,RPC 调用和文件操作将会非常大,从而对 HDFS 负载造成很大压力,成为瓶颈。可能由于以下原因导致 HDFS 写入失败、WAL Split 和 Region 上线缓慢超时重试。

  • 巨大的预留磁盘空间。

  • 并发访问达到 DataNode 的 xceiver 的限制。

HMaster 负载

​ 

HMaster 使用基于 ZooKeeper 的分配机制时,在 Region 上线过程中 HMaster 会创建一个 OFFLINE ZNode 节点,RegionServer 会将该 ZNode 更新为 OPENING 和 OPENED 状态。对于每个状态变化,HMaster 都会进行监听并处理。

​ 

对于 100 个节点的 HBase 集群,大概将会有 6,000,000 个 ZNode 创建和更新操作和 4,000,000 个监听事件要进行处理。


ZooKeeper 的监听事件通知处理是顺序的,旨在保证事件的顺序。这种设计在 Region 锁获取阶段将会导致延迟。在 10 个节点的集群中发现等待时间为 64 秒,而 20 节点的集群中等待时间为 111 秒。



GeneralBulkAssigner 在批量发送 OPENRPC 请求到 RegionServer 之前会获取相关 Region 的锁,再收到 RegionServer 的 OPEN RPC 请求响应时才会释放该锁。如果 RegionServer 再处理批量 OPEN RPC 请求时需要时间,那么在收到确认响应之前 GeneralBulkAssigner 将不会释放锁,其实部分 Region 已经上线,也不会单独处理这些 Region。


HMaster 按照顺序创建 OFFLINE ZNode 节点。观察发现在执行批量分配 Region 到 RegionServer 之前将会有 35 秒的延迟来创建 ZNode。



采用不依赖 ZooKeeper 的分配机制将会减少 ZooKeeper 的操作,可以有 50%左右的优化。HMaster 依然会协调和处理 Region 的分配。

提升 WAL Split 性能

持久化 FlushedSequenceId 来加速集群重启 WAL Split 性能(HBASE-20727)

​ 

ServerManager 有每个 Region 的 flushedSequenceId 信息,这些信息被保存在一个 Map 结构中。我们可以利用这些信息来过滤不需要进行回放的记录。但是这个 Map 结构并没有被持久化,当集群重启或者 HMaster 重启后,每个 Region 的 flushedSequenceId 信息将会丢失。


如果这些信息被持久化那么即使 HMaster 重启,这些依然存在可用于过滤 WAL 记录,加快恢复记录和回放。‘hbase.master.persist.flushedsequenceid.enabled’可用于配置是否开启此功能。flushedSequenceId 信息将会定时持久化到如下目录<habse root dir>/.lastflushedseqids。可以通过参数’hbase.master.flushedsequenceid.flusher.interval’ 来配置持久化间隔,默认为 3 小时。


注意:此特性在 HBase 1.X 版本不可用。

改善 WAL Split 在故障切换时稳定性(HBASE-19358)

​ 

在 WAL 记录恢复期间,WAL Split 任务将会将 RegionServer 上的所有待恢复记录输出文件打开。当 RegionServer 上管理的 Region 数量较多时将会影响 HDFS,需要大量的磁盘保留空间但是磁盘写入非常小。

​ 

当集群中所有 RegionServer 节点都重启进行恢复时,情况将变得非常糟糕。如果一个 RegionServer 上有 2000 个 Region,每个 HDFS 文件为 3 副本,那么将会导致每个 WALSplitter 打开 6000 个文件。

​ 通过启用 hbase.split.writer.creation.bounded 可以限制每个 WAL Splitter 打开的文件。当设置为 true 时,不会打开任何 recovered.edits 的写入直到在内存积累的记录已经达到 hbase.regionserver.hlog.splitlog.buffersize(默认 128M),然后一次性写入并关闭文件,而不是一直处于打开状态。这样会减少打开文件流数量,从 hbase.regionserver.wal.max.splitters * the number of region the hlogcontains 减少为 hbase.regionserver.wal.max.splitters *hbase.regionserver.hlog.splitlog.writer.threads。

​ 

通过测试发现在 3 节点集群中,拥有 15GBWAL 文件和 20K Region 的情况下,集群整体重启时间从 23 分钟缩短为 11 分钟,减少 50%。

hbase.regionserver.wal.max.splitters = 5

hbase.regionserver.hlog.splitlog.writer.threads= 50

WAL Split 为 HFile(HBASE-23286)

​ 

WAL 恢复时使用 HFile 文件替换 Edits 文件这样可以避免在 Region 上线过程中写入。Region 上线过程中需要完成 HFile 文件校验、执行 bulkload 加载并触发 Compaction 来合并小文件。此优化可以避免读取 Edits 文件和持久化内存带来的 IO 开销。当集群中的 Region 数量较少时(例如 50 个 Region)观察发现性能有显著提升。

​ 

当集群中有更多的 Region 时,测试发现由于大量的 HFile 写入和合并将会导致 CPU 和 IO 的增加。可以通过如下额外的措施来减少 IO。

  • 将故障 RegionServer 作为首选 WALSplitter,减少远程读取。

  • 将 Compaction 延迟后台执行,加快 region 上线处理。

Observer NameNode(HDFS-12943)

​ 

当 HBase 集群规模变大时,重启会触发大量的 RPC 请求,使得 HDFS 可能成为瓶颈,可以通过使用 Observer NameNode 负担读请求来降低 HDFS 的负载。

总结


通过上述分析,可以配置如下参数来提升 HBase MTTR,尤其是在集群整体从崩溃中恢复的情况。



参考

  • HBase ZK-less Region Assignment : Apache HBase

  • Apache HBase ™ Reference Guide

  • NoSQL HBase schema design and SQL with Apache Drill(slideshare.net)

  • MapReduce 服务 MRS_华为云 (huaweicloud.com)


点击关注,第一时间了解华为云新鲜技术~

发布于: 2 小时前阅读数: 4
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
Apache HBase MTTR 优化实践:减少恢复时长