HBase物理模型
Client
- 使用HBase RPC机制与HMaster和HRegionServer进行通信
- Client与HMaster进行通信进行管理类操作
- Client与HRS进行数据读写类操作
- 包含访问HBase的接口,并维护缓存cache来加快对HBase的访问,比如HR的位置信息。
- 在启动一个Client到HBase集群的连接时,Client至少拿到集群中ZooKeeper的位置。这样,Client才能访问ZooKeeper层次,了解集群的属性,如服务器的位置等等。
HMaster
HBase中可以启动多个HMaster,通过Zookeeper保证总有一个Active Master运行。主要负责Table和Region的管理工作:
- 管理用户对Table的增删改操作
- 发现失效的HRS重新分配其上的HR,并负责管理HRS的负载均衡,调整Region分布
- Region Split后,负责新Region的分布
- Client访问HBase数据的过程中并不需要HMaster参与【寻址访问ZK和HRS,数据读写访问HRS】HMaster仅仅维护者Table和HR的元数据信息,负载很低
HRegion和HRegion Server
主要负责响应用户I/O请求,向HDFS文件系统中读写数据,HBase中最核心的模块。
- 一台物理节点只能跑一个HRegion Server(HRS),一个HRS管理多个HRegion()。
- HRS负责切分HR:最初只有一个HR,当记录数超过某个阈值时,开始分裂成两个HR,并由HMaster实现负载均衡,分配到其他的HRS。
- HBase Table中的数据按照Row Key字典顺序排列,Table 在行的方向上分割为多个Region,每个子Region分散在不同的RegionServer中。
- Region是实现分布式存储和负载均衡的最小单元,Store File是存储的最小单元。
- 一个HR包括一个HLog和多个Store,一个Store包含一个Mem Store(内存数据)和多个Store File(磁盘数据), 每个Store File保存一个Columns Family,其中Store File存储在HDFS上,对应为HFile文件。
HLog(WAL Log)日志
引入HLog原因:在分布式系统环境中,无法避免系统出错或者宕机,一旦HRS意外退出,MemStore中的内存数据就会丢失,引入HLog就是防止这种情况。
- 每个HRS中都包含一个HLog文件,HLog是一个实现Write Ahead Log的类。在用户每次写入操作时,会在写入Mem Store的同时,也会写一份数据到HLog中。
- HLog存放在HDFS上,会定期回滚产生新的,并删除旧的文件(已持久化到Store File中的数据)。
- 当HRS意外终止后,HMaster会通过ZK感知到,HMaster根据HR的不同对HLog进行拆分Split,并分配给对应的HR。领取到这些HLog的HRS在Load HRegion的过程中,发现有历史HLog需要处理,因此会“重做”Replay HLog中的数据到Mem Store中,然后Flush到Store File,完成数据恢复。
-
每个Region Server维护一个Hlog,而不是每个Region一个。这样不同Region(来自不同table)的日志会混在一起,这样做的目的是不断追加单个文件相对于同时写多个文件而言,可以减少磁盘寻址次数,因此可以提高对table的写性能。带来的麻烦是,如果一台Region Server下线,为了恢复其上的Region,需要将Region Server上的log进行拆分,然后分发到其它Region Server上进行恢复。
Mem Store与Store File
- 每个HRgion保存一个表的所有数据(起初, 以后会分裂),一个HRegion包含多个Stroe,每个Store保存一个Column Family的所有数据。
- 一个列族可以有多个StoreFile,但一个StoreFile只能存储一个列族的数据。
- 一个Store包括一个位于内存的Mem Store和多个位于硬盘的Store File。
- 客户端检索数据时,先在Mem Store找,找不到再找Store File。
-ROOT- 和 .META. 表
- .META.表:记录了用户表对应的HRS信息,由于.META.表太大,会被切分成多个HR,存储在不同的HRS中。
- -ROOT-表:记录了.META.表对应的HRS信息,-ROOT-表只有一个HR。
- ZK中保存了-ROOT-表对应的HRS位置,默认的路径是 "/hbase/root-region-server"
- 读取数据的流程:ZooKeeper --> -ROOT-(单Region) --> .META. --> HRS --> 用户Table。多次网络操作,不过client端有cache缓存
ZooKeeper作用
- HBase依赖(ZooKeeper)提供消息通信机制。通过选举,保证任何时候,集群中只有一个HMaster。ZK的引入使得HMaster不再是单点故障。HBase分布式模式最好需要(3)个节点,这是因为ZK的原因。
- Zookeeper Quorum存储-ROOT-表地址(所有Region的寻址入口)、HMaster地址。
- HMaster与HRS启动时会向ZK注册,并定时向ZK发送心跳。实时监控HRS的状态,将HRS上线和下线信息实时通知给HMaster。
- 默认情况下,HBase 管理ZK 实例,比如:启动或者停止ZK。
- 每个行操作可能要访问三次远程节点。为了节省这些代价,Client会缓存cash(它遍历-ROOT-时获取的信息和.META.位置以及user-space region的开始行和结束行)。这样,Client以后就不需要访问.META.表也能得知HR存放的位置。Client在碰到错误之前会一直使用所缓存的项。当发生错误时---即Region被移动了---Client会再去查看.META.获取user-space Region的新位置。如果.META.的Region也被移动了,Client会再去查看-ROOT-。
HBase存储格式
HBase中的所有数据文件都存储在HDFS上,主要有两种格式:
- HFile:HBase中KeyValue数据的存储格式,是Hadoop的二进制格式文件,有固定的结构。实际上StoreFile就是对HFile做了轻量级包装,即StoreFile底层就是HFile
- HLog:HBase中WAL(Write Ahead Log)的存储格式,物理上是Hadoop的Sequence File
HFile模型
- Data Block 段:保存表中的数据,这部分可以被压缩。Data Block是HBase I/O的基本单元,为了提高效率,HRegionServer中有基于LRU的Block Cache机制。每个Data Block的大小可以在创建一个Table的时候通过参数指定,大型的Block有利于顺序Scan,小型的Block利于随机查询。每个Data Block除了开头的Magic以外就是一个个KeyValue对拼接而成,Magic内容就是一些随机数字,目的是防止数据损坏,Magic Number用来做安全check。
- Meta Block 段(可选的):保存用户自定义的kv对,可以被压缩
- File Info 段:这一段是定长的,保存Hfile的元信息,不被压缩,用户也可以在这一部分添加自己的元信息。
- Data Index 段:Data Block的索引,记录着每个Data Block的起点,即第一条记录的key
- Meta Index段 (可选的):Meta Block的索引,记录着每个Meta Block的起点
- Trailer段:这一段是定长的,保存了每一段的偏移量,读取一个HFile时,会首先读取Trailer,Trailer保存了每个段的起始位置(段的Magic Number用来做安全check),然后,DataBlock Index会被读取到内存中,这样,当检索某个key时,不需要扫描整个HFile,而只需从内存中找到key所在的block,通过一次磁盘io将整个block读取到内存中,再找到需要的key。DataBlock Index采用LRU机制淘汰。
- HFile的Data Block,Meta Block通常采用压缩方式存储,压缩之后可以大大减少网络IO和磁盘IO,随之而来的开销当然是需要花费cpu进行压缩和解压缩。目前Hfile的压缩支持两种方式:Gzip,Lzo。
读请求处理过程(无需借助HMaster)
- 首先查看ZK中的-ROOT-表找到.META.表,通过.META.中的记录查找对应HRS中的HR内存数据Mem Store,如果在Mem Store中找到了需要的版本,直接返回即可。
- 否则,按照次序从新到旧检查Store File,直到找到满足查询的version,或者所有Store File都处理完为止。