摘要:HBase 是 Hadoop Database 的简称,是建设在 Hadoop 文件系统之上的分布式面向列的数据库,它具备高牢靠、高性能、面向列和可伸缩的个性,提供疾速随机拜访海量数据能力。
本文分享自华为云社区《Apache HBase MTTR 优化实际》,作者:pippo。
HBase 介绍
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(Write Ahead 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 在批量发送 OPEN RPC 申请到 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 正本,那么将会导致每个 WAL Splitter 关上 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 hlog contains 缩小为 hbase.regionserver.wal.max.splitters hbase.regionserver.hlog.splitlog.writer.threads。
通过测试发现在 3 节点集群中,领有 15GB WAL 文件和 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 作为首选 WAL Splitter,缩小近程读取。
- 将 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 (http://slideshare.net)
- MapReduce 服务 MRS_华为云 (huaweicloud.com)
点击关注,第一工夫理解华为云陈腐技术~