赞
踩
本文致力于从架构原理、集群部署、性能优化与使用技巧等方面,阐述在如何基于HBase构建容纳大规模数据、支撑高并发、毫秒响应、稳定高效的OLTP实时系统 。

从上层往下可以看到HBase架构中的角色分配为:
Client——>Zookeeper——>HMaster——>RegionServer——>HDFS
Client是执行查询、写入等对HBase表数据进行增删改查的使用方,可以是使用HBase Client API编写的程序,也可以是其他开发好的HBase客户端应用。
Zookeeper同HDFS一样,HBase使用Zookeeper作为集群协调与管理系统。
在HBase中其主要的功能与职责为:
协调过程示意图如下:

除了作为集群中的协调者,Zookeeper还为Client提供了 hbase:meta 表的存储信息。
客户端要访问HBase中的数据,只需要知道Zookeeper集群的连接信息,访问步骤如下:
可以看到,客户端操作数据过程并不需要HMaster的参与,通过Zookeeper间接访问RegionServer来操作数据。
第一次请求将会产生3次RPC,之后使用相同的rowkey时,客户端将直接使用缓存下来的位置信息,直接访问RegionServer,直至缓存失效(Region失效、迁移等原因)。
通过Zookeeper的读写流程如下:

hbase:meta 表存储了集群中所有Region的位置信息。
表结构如下:

| rowkey规则:${表名},${起始键},${region时间戳}.${encode编码}. |
| 列簇:info |
| 列 |
| state:Region状态,正常情况下为 OPEN |
| serverstartcode:RegionServer启动的13位时间戳 |
| server:所在RegionServer 地址和端口,如cdh85-47:16020 |
| sn:server和serverstartcode组成,如cdh85-47:16020,1549491783878 |
| seqnumDuringOpen:Region在线时长的二进制串 |
| regioninfo:region的详细信息,如:ENCODED、NAME、STARTKEY、ENDKEY等 |
| ENCODED:基于${表名},${起始键},${region时间戳}生成的32位md5字符串, region数据存储在hdfs上时使用的唯一编号,可以从meta表中根据该值定位到hdfs中的具体路径。 rowkey中最后的${encode编码}就是 ENCODED 的值,其是rowkey组成的一部分。 |
| NAME:与ROWKEY值相同 |
| STARTKEY:该region的起始键 |
| ENDKEY:该region的结束键 |
简单总结Zookeeper在HBase集群中的作用如下:

如我们前面所说的,HMaster 通过 Zookeeper 实现对集群中,各个 RegionServer 的监控与管理,在RegionServer 发生故障时,可以发现节点宕机,并转移 Region 至其他节点,以保证服务的可用性。
但是HBase的故障转移并不是无感知的,相反故障转移过程中,可能会直接影响到线上请求的稳定性,造成段时间内的大量延迟。
在分布式系统的 CAP定理中(Consistency一致性、Availability可用性、Partition tolerance分区容错性),分布式数据库基本特性都会实现P,但是不同的数据库对于A和C各有取舍。
如HBase选择了C,而通过Zookeeper这种方式来辅助实现A(虽然会有一定缺陷),而Cassandra选择了A,通过其他辅助措施实现了C,各有优劣。
对于HBase集群来说,HMaster是一个内部管理者,除了DDL操作并不对外(客户端)开放,因而HMaster的负载是比较低的。
造成HMaster压力大的情况,可能是集群中存在多个(两个或者三个以上)HMaster,备用的Master会定期与Active Master通信,以获取最新的状态信息,以保证故障切换时自身的数据状态是最新的,因而Active Master可能会收到大量来自备用Master的数据请求。
RegionServer在HBase集群中的功能与职责:
RegionServer内部结构图如下:

BlockCache为RegionServer中的读缓存,一个RegionServer共用一个BlockCache。
RegionServer处理客户端读请求的过程:
BlockCache有两种实现方式,有不同的应用场景,各有优劣:
我们将在「性能优化」一节中具体讨论如何判断应该使用哪种内存模式。
全称 Write Ahead Log ,是 RegionServer 中的预写日志。
所有写入数据,默认情况下,都会先写入WAL中,以保证RegionServer宕机重启之后,可以通过WAL来恢复数据,一个RegionServer中共用一个WAL。
RegionServer的写流程如下:
WAL会通过日志滚动的操作,定期对日志文件进行清理(已写入HFile中的数据可以清除),对应HDFS上的存储路径为 /hbase/WALs/${HRegionServer_Name} 。
一个Table由一个或者多个Region组成,一个Region中可以看成是Table按行切分且有序的数据块,每个Region都有自身的StartKey、EndKey。
一个Region由一个或者多个Store组成,每个Store存储该Table对应Region中一个列簇的数据,相同列簇的列,存储在同一个Store中。
同一个Table的Region,会分布在集群中不同的RegionServer上,以实现读写请求的负载均衡。故,一个RegionServer中,将会存储来自不同Table的N多个Region。
Store、Region与Table的关系可以表述如下:多个Store(列簇)组成Region,多个Region(行数据块)组成完整的Table。
其中,Store由Memstore(内存)、StoreFile(磁盘)两部分组成。
在RegionServer中,Memstore可以看成指定Table、Region、Store的写缓存(正如BlockCache小节中所述,Memstore还承载了一些读缓存的功能),以RowKey、Column Family、Column、Timestamp进行排序。如下图所示:

写请求到RegionServer之后,并没有立刻写入磁盘中,而是先写入内存中的Memstore(内存中数据丢失问题,可以通过回放WAL解决)以提升写入性能。
Region中的Memstore,会根据特定算法,将内存中的数据,将会刷写到磁盘,形成Storefile文件,因为数据在Memstore中为已排序,顺序写入磁盘性能高、速度快。
在这种 Log-Structured Merge Tree架构模式下,随机写入HBase拥有相当高的性能。
Memstore刷磁盘形成的StoreFile,以HFile格式,存储HBase的KV数据于HDFS之上。
HDFS为HBase提供底层存储系统,通过HDFS的高可用、高可靠等特性,保障了HBase的数据安全、容灾与备份。
对于客户端来说,将请求发送到需要写入的RegionServer中,等待RegionServer写入WAL、Memstore之后,即返回写入成功的ack信号。
对于RegionServer来说,写入的数据,还需要经过一系列的处理步骤。
首先我们知道Memstore是在内存中的,将数据放在内存中,可以得到优异的读写性能,但是同样也会带来麻烦:
对于第一个问题,虽然可以通过WAL机制在重启的时候,进行数据回放,但是对于第二个问题,则必须将内存中的数据持久化到磁盘中。
在不同情况下,RegionServer通过不同级别的刷写策略,对Memstore中的数据进行持久化,根据触发刷写动作的时机,以及影响范围,可以分为不同的几个级别:
Memstore刷写时,会阻塞线上的请求响应,由此可以看到,不同级别的刷写,对线上的请求,会造成不同程度影响的延迟:
所以在Memstore的刷写方面,需要尽量避免出现RegionServer级别的刷写动作。
数据在经过Memstore刷写到磁盘时,对应的会写入WAL sequence的相关信息,已经持久化到磁盘的数据,就没有必要通过WAL记录的必要。
RegionServer会根据这个sequence值,对WAL日志进行滚动清理,防止WAL日志数量太多,RegionServer启动时,加载太多数据信息。
同样,在Memstore的刷写策略中,可以看到,为了防止WAL日志数量太多,达到指定阈值之后,将会选择WAL记录中,最早的一个或者多个Region进行刷写。
经过前文的了解,我们现在可以知道HBase中一条数据完整的读取操作流程中,Client会和Zookeeper、RegionServer等发生多次交互请求。
基于HBase的架构,一条数据可能存在RegionServer中的三个不同位置:
RegionServer接收到的一条数据查询请求,只需要从以上三个地方,检索到数据即可。
在HBase中的检索顺序依次是:BlockCache -> Memstore -> HFiles。
其中,BlockCache、Memstore都是直接在内存中进行高性能的数据检索。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。