原创 老时与阿丞 PowerData

本文由PowerData时老师与PowerData阿丞联合贡献


全文共 3452 个字,建议阅读 14 分钟

文章脑图

前置知识

Zookeeper

Zookeeper是一个基于观察者模式设计的分布式服务管理框架,其主要功能就是维护配置信息、命名、提供分布式同步和组成员服务,其只能满足分布式系统CAP法则中的C和P,是因Zookeeper会因为网络波动可能造成的通信问题和Leader挂掉重新选举时造成是ZK整体服务不可用的情况。

CAP分别是一致性(C)、可用性(A)、分区容错性(P)。

Zookeeper组成及架构

  • Client:客户端通信
  • Leader:处理事务请求,更新系统状态、进行投票的发起和决议
  • Follower:处理客户端非事务请求并向客户端返回结果,将写事务请求转发给Leader、参与选举投票,并同步Leader的状态
  • Observer:接收客户端读请求,将客户端写请求转发给Leader,不参与投票过程,只同步Leader的状态

Zookeeper数据模型

Zookeeper的数据模型类似于文件树一样,Znode是Zookeeper中数据的最小单元,可以保存数据。通过挂载子节点构成一个树状的层次化命名空间。

  • /
  • /app1/data1
  • /app2/data2
  • /app1
  • /app2

Hbase

Hbase是一个分布式、支持海量数据存储的NoSQL数据库,其数据以Key-Value的形式存储进行存储。

Hbase组成及架构

  • Master:是Hbase集群中的主节点,负责管理和协调整个集群的工作、管理RegionServer以及故障恢复、元数据管理、表的操作等
  • RegionServer:是Hbase集群中的具体工作节点,主要负责管理region和存储一部分数据、处理客户端的读写请求和处理数据的刷写、压缩等操作,其存储架构如下:
  • Memstore:写缓存,基于内存,文件会在其中排序,达到阈值后Flush到StoreFile中
  • StoreFile:基于HDFS的存储Key-Value文件
  • Block Cache:读缓存,基于内存,查询到的数据会缓存在Block Cache中
  • WAL:预写日志,主打一个保证数据不丢失,主要是防止RegionServer挂了导致数据丢失
  • Region
  • Zookeeper:是Hbase集群中的协调服务,主要负责管理和维护集群的元数据和状态信息、负责集群间通信、故障恢复等
  • HDFS:是Hbase集群中的存储,数据以region的形式存储在HDFS上,每个region对应一个块(block)

Hbase数据模型

  • 表(table):一个表由一个或者多个列族组成
  • 行(row):一个行包含了多个列,每一行代表一个数据对象,每一行都以行键(Row Key)来进行唯一标识,这些列通过列族来分类
  • 列族(column family):列族是多个列的集合
  • 列(column):多个列组成一个行
  • 单元格(cell)::一个列中可以存储多个版本的数据,每个版本就称为一个单元格
  • 时间戳(timestamp):用来标记同一个列中多个单元格的版本号

Hbase的几个重要操作

对于Hbase来讲,比较重要的几个操作:

  • Flush:Flush是指将内存数据持久化到磁盘,也就是Memstore刷写到StoreFile的过程,其包括数据写入磁盘、更新StoreFile索引、清空内存等操作。其刷写时机如下:
  • 某个memstore的大小达到Hbase Memstore刷新大小,其所在Region的所有memstore都会刷写
  • Region Server中memstore总大小达到 Java\_Heap * Region Server中memstore最大大小 * memstore里的阈值,region按照memstore大小顺序依次刷写,直到Region Server中所有的memstore的总大小减少到上述值后停止
  • 定时刷写(俩个参数,时间和大小)
  • WAL文件数量超过提前写入日志(WAL)文件的最大数量时,region会按照时间顺序依次刷写
  • 手动刷写
  • Compaction:StoreFile合并,Hbase有Major Compaction和Minor Compaction俩种。
  • Major Compaction:简称“大合并”,大合并是指将一个Store下的所有StoreFile进行合并,并且清理所有有delete标记和过期的数据。
  • Minor Compaction:简称“小合并”,小合并是指将临近的几个StoreFile进行合并,并清理部分有delete标记和过期的数据。
  • Compaction有自动合并和手动合并,自动合并会根据参数设置
  • Split:Region切分,Region的数量和预分区的数量有关,一般情况下,建表不手动设置预分区,该表就会只有一个region,随着数据写入,region在达到一定数量以后会进行切分,且俩个region都会处于一个RegionServer上,后面触发重平衡以后Hmaster可能会将某个Region转移到其他RegionServer上。

需要注意的是,以上三个操作在集群中建议关闭自动,手动进行,每一个操作都会消耗集群资源,影响集群的稳定性和性能。

HMaster选举与主备切换

HMaster选举与主备切换的原理和HDFS中NameNode及YARN中ResourceManager的HA原理相同。

在Hadoop中,HDFS的NameNode主要用于管理HDFS的元数据和统筹各个DataNode的工作,由于NameNode是Hadoop集群的单点故障,因此生产环境中一般都需要配置HA来保证集群的高可用性。

HMaster的选举与主备切换、Yarn的ResourceManager、HDFS的NameNode的HA都是通过Active-Standby机制来实现的,在Active节点发生故障时,自动切换到Standby节点,保证集群的高可用性,其原理如下:

  1. Active节点:在HA机制中,只有一个节点(主节点)处于Active状态,负责管理整个集群的。Active节点会定期向ZooKeeper发送心跳信息,以保证其正常运行。
  2. Standby节点:在HA机制中,另一个节点(备节点)处于Standby状态,等待Active节点出现故障时接管其工作。Standby节点会从ZooKeeper中获取Active节点的状态信息,并定期检查Active节点的状态,以保证其能够及时接管其工作。
  3. ZooKeeper:在HA机制中,ZooKeeper用于存储和管理Active节点和Standby节点的状态信息。Active 节点会定期向ZooKeeper发送心跳信息,以保证其正常运行。Standby节点会从ZooKeeper中获取Active 节点的状态信息,并定期检查Active节点的状态,以保证其能够及时接管其工作。
  4. 自动切换:当Active节点出现故障时,Standby节点会自动接管其工作,并成为新的Active节点。此时,HDFS集群的所有元数据和协调工作都由新的Active节点负责。

系统容错

当HBase启动时,每个RegionServer都会到ZooKeeper的/hbase/rs节点下创建一个信息节点(下文中,我们称该节点为”rs状态节点”),例如/hbase/rs/[Hostname],同时,HMaster会对这个节点注册监听。当某个 RegionServer 挂掉的时候,ZooKeeper会因为在一段时间内无法接受其心跳(即 Session 失效),而删除掉该 RegionServer 服务器对应的 rs 状态节点。与此同时,HMaster 则会接收到 ZooKeeper 的 NodeDelete 通知,从而感知到某个节点断开,并立即开始容错工作。

思考:HBase为什么不直接让HMaster来负责RegionServer的监控呢?

如果HMaster直接通过心跳机制等来管理RegionServer的状态,随着集群越来越大,HMaster的管理负担会越来越重,另外它自身也有挂掉的可能,因此数据还需要持久化。在这种情况下,ZooKeeper就成了理想的选择。

RootRegion管理

对应HBase集群来说,数据存储的位置信息是记录在元数据region,也就是RootRegion上的。

每次客户端发起新的请求,需要知道数据的位置,就会去查询RootRegion,而RootRegion自身位置则是记录在ZooKeeper上的(默认情况下,是记录在ZooKeeper的/hbase/meta-region-server节点中)。

当RootRegion发生变化,比如Region的手工移动、重新负载均衡或RootRegion所在服务器发生了故障等是,就能够通过ZooKeeper来感知到这一变化并做出一系列相应的容灾措施,从而保证客户端总是能够拿到正确的RootRegion信息。

Region管理

HBase里的Region会经常发生变更,这些变更的原因来自于系统故障、负载均衡、配置修改、Region分裂与合并等。一旦Region发生移动,它就会经历下线(offline)和重新上线(online)的过程。

当Region发生移动时,其上线的过程如下:

  1. RegionServer检查目标RegionServer是否可用,如果可用,则将Region的元数据更新为目标RegionServer的地址。
  2. 目标RegionServer接受Region的请求,并将Region的数据从源RegionServer复制到本地。
  3. 目标RegionServer更新Region的状态为“打开”,并通知HMaster更新Region的状态。

当Region发生移动时,其下线的过程如下:

  1. RegionServer将Region的状态更新为“下线”,并通知HMaster更新Region的状态。
  2. HMaster将Region的元数据更新为其他RegionServer的地址,并将Region的状态更新为“正在分裂”或“正在合并”。
  3. 其他RegionServer接受Region的请求,并将Region的数据从源RegionServer复制到本地。
  4. 其他RegionServer更新Region的状态为“打开”,并通知HMaster更新Region的状态。

分布式SplitWAL任务管理

当某台RegionServer服务器挂掉时,由于总有一部分新写入的数据还没有持久化到HFile中,因此在迁移该RegionServer的服务时,一个重要的工作就是从WAL中恢复这部分还在内存中的数据,而这部分工作最关键的一步就是SplitWAL,即HMaster需要遍历该RegionServer服务器的WAL,并按Region切分成小块移动到新的地址下,并进行日志的回放(replay)。

由于单个RegionServer的日志量相对庞大(可能有上千个Region,上GB的日志),而用户又往往希望系统能够快速完成日志的恢复工作。因此一个可行的方案是将这个处理WAL的任务分给多台RegionServer服务器来共同处理,而这就又需要一个持久化组件来辅助HMaster完成任务的分配。

当前的做法是,HMaster会在ZooKeeper上创建一个SplitWAL节点(默认情况下,是/hbase/SplitWAL节点),将“哪个RegionServer处理哪个Region”这样的信息以列表的形式存放到该节点上,然后由各个RegionServer服务器自行到该节点上去领取任务并在任务执行成功或失败后再更新该节点的信息,以通知HMaster继续进行后面的步骤。ZooKeeper在这里担负起了分布式集群中相互通知和信息持久化的角色。

小结

以上就是一些HBase中依赖ZooKeeper完成分布式协调功能的典型场景。

但事实上,HBase对ZooKeepr的依赖还不止这些,比如HMaster还依赖ZooKeeper来完成Table的enable/disable状态记录,以及HBase中几乎所有的元数据存储都是放在ZooKeeper上的。

由于ZooKeeper出色的分布式协调能力及良好的通知机制,HBase在各版本的演进过程中越来越多地增加了ZooKeeper的应用场景,从趋势上来看两者的交集越来越多。HBase中所有对ZooKeeper的操作都封装在了org.apache.hadoop.hbase.zookeeper这个包中,感兴趣的同学可以自行研究。


想要加入社区或对本文有任何疑问,可直接添加社区联系人微信。


我们是由一群数据从业人员,因为热爱凝聚在一起,以开源精神为基础,组成的PowerData数据之力社区。

可关注下方公众号后点击“加入我们”,与PowerData一起成长。


PowerData
1 声望2 粉丝

PowerData社区官方思否账号