一起再看下Hbase的架构细节。
整体架构
HBase在集群架构上一般分为三种类型的服务器:
RegionServer用来处理数据的读写,当我们访问数据的时候,可以直接到RegionServer上获取。
Master一般处理Region的分配,Region的分裂,Hbaose表的创建删除
ZooKeeper 维护集群的状态
在Hadoop集群中,RegionServer管理的数据主要存储在DataNode上,所有的Hbase数据都会以HDFS的文件形式存储。RegionServer一般是HDFS的DataNode,当Hbase的数据刚写入的时候,它一般存储在本地,但是当Region被移动的时候,一般就不在本地了。
如下图:
Regions
Hbase的表一般按照范围划分为多个Region,Region内部主要包含表startKey和endKey之间的数据,Region会被分配到集群的Region Server上,一个RegionServer可以处理大约1000个Region。
Master
HBase的Master主要负责Region的分配,表的创建和删除等处理
协调RegionServer,在RegionServer启动的时候,分配Region给RegionServer,在负载均衡或者故障恢复的时候分配Region。
监控所有RegionServer实例在集群中的状态,主要通过监听ZooKeeper的通知来实现。
管理员的接口:创建,删除,更新表
RegionServer
RegionServer运行在HDFS的DataNode上面,它有如下的组件:
WAL:预写日志,用来储存还没有被持久化的数据,可以用于故障的时候恢复数据
BlockCache: 读缓存,在内存中存储经常被读取的数据,当BlockCache满的时候,使用LRU算法淘汰数据。
MemStore:写缓存,当数据还没有被持久化到磁盘的时候,存储新的数据。在写入磁盘之前会进行一次排序,一般每个Region的每个列簇会有一个MemStore。
HFile:存储Hbase表的行数据,以排好序的KeyValue形式存储在磁盘上
ZooKeeper
Hbase使用ZooKeeper作为分布式协调服务来维护服务器集群的状态,ZooKeeper维护正在运行的和可以使用的服务器,如果有服务器失败,ZooKeeper会发送失败通知。ZooKeeper可以保证一致性,一般会部署3-5个ZooKeeper节点来保证一致性。
组件之间的配合
ZooKeeper负责协调集群中的状态,提供共享的状态信息。RegionServer和Master都会维护一个ZooKeeper的会话,ZooKeeper通过心跳和临时节点来维护活跃的会话。
每个RegionServer都会创建一个临时的节点,Master监控这些临时节点,在竞选Master的时候,多个节点同时像ZooKeeper的一个节点上创建临时节点,ZooKeeper通过判断是那一个节点第一个创建的,来判断谁作为Master节点,Master节点像ZooKeeper发送心跳信息,如果有备份的Master节点,可以监听主Master节点的信息来判断主Master是否存活。
如果Master或者RegionServer挂掉的时候,它们与ZooKeeper的会话就会断掉,临时节点也会被删除掉,监听者能够收到这些通知,如果Master收到了RegionServer的故障通知,它会试着恢复故障的RegionServer,如果Master节点挂了,备份的Master节点升级为主Master节点。
HBase写流程
当客户端发出一个写请求到RegionServer的时候,首先写入WAL日志,一旦数据写入WAL成功,再把数据写入MemStore,然后返回确认消息给客户端。
MemStore在内存中以KeyValue的形式存储数据,存储方式同HFile。每个列簇在一个Store中只有一个MemStore.
当MemStore增大到一定程度的时候,它里面的数据就会写入到HDFS上的一个新的HFile。HBase的每个列簇有多个Hfiles。
另外这个也是为什么HBase的列簇数量有限制的原因,一般每个列簇在一个Store中只有一个MemStore,当其中任何一个MemStore满了,所有的MemStore都会刷新,每次刷新的时候都会保存一个序列号,新的刷新也知道上次刷新的序列号,这样系统就知道当前持久化的状态了。序列化的号码会作为HFile的元数据,当Region启动的时候,Region读取Hfile中的元数据信息,可以得知最大的序列号。
Hfile的存储
HFile格式
HFile包含多层的index,这样在HBase查找数据的时候不用将完整的HFile都加载到内存中,多层index有点像B+树。
KeyValue 以递增的方式存储。
每个Block都有自己的叶子索引
root索引,指向中间的index
当HFile被打开的时候,index被加载到内存中BlockCache,这样可以保证在查询的时候有更高的性能。
Hbase读合并
从上面的描述,我们知道每一个row对应的KeyValue可能出现在多个地方,row被持久化到磁盘的HFiles,最新的更新则在MemStore,最新的读则使用BlockCache。当读取一行的时候,系统如何获取一致性的结果?这里主要用的是读合并:
首先,scanner查看BlockCache中的值,BlockCache存储的是最新的读缓存,BlockCache会使用LRU淘汰策略。
下一步,sanner查看MemStore中的值,MemStore内部则是最新的更新操作。
如果Scanner在MemStore和BlockCache中都没有发现值,Hbase会使用Block Cache的索引,和布隆过滤器,加载Hfile到内存中,查看值是否在Hfile中。
Hbase压缩
Hbase会自动的挑选一些小的HFile,然后重写他们到一些更大的HFile中,这个过程叫做小的合并(Minor Compaction)。小合并主要用来减少HFile的数量。
大的合并(Major Compaction)合并和重写一个Region中的所有HFile,按照列簇,每个列簇只有一个HFile。同时删除过期的Cell,这样可以改善读性能。另外,因为大合并重写所有的文件,会有很大的消耗。一般在周末和晚上的时候调度执行。
Region分裂
刚开始的时候每个表只有一个Region,当Region变的特别大的时候,它被分隔成两个Region。分隔的Region各自持有原Region一半的数据,然后分裂会报告给Master。然后有时候,Master会将新分裂的Region移动到其它的RegionServer上面。
Hbase故障恢复
当某个RegionServer挂掉的时候,Master节点通过ZooKeeper可以感知到节点的故障,然后HMaster重新分配故障节点的Region到其它的RegionServer上,有些数据在故障的节点MemStore和WAL中,还没有持久化到磁盘,Master节点会将WAL划分为多个小文件,然后每个RegionServer负责重新执行WAL文件中的内容,来重建MemStore。最后再将MemStore刷新到磁盘中。
HBase缺点
Hbase当然也是有一些缺点的:
WAL 恢复的时候过于慢
Major Compaction的时候有IO风暴
最后
这里主要说了一些Hbase的架构。
参考
注:
本文独家发布自金蝶云社区
推荐阅读