HBase采用Master/Slave架构搭建集群,它隶属于Hadoop生态系统,由以下类型节点组成:HMaster节点、HRegionServer节点、ZooKeeper集群,而在底层,它将数据存储于HDFS中,因而涉及到HDFS的NameNode、DataNode等,总体结构如下:
其中HMaster节点用于:
- 管理HRegionServer,实现其负载均衡。
- 管理和分配HRegion,比如在HRegion split时分配新的HRegion;在HRegionServer退出时迁移其内的HRegion到其他HRegionServer上。
- 实现DDL操作(Data Definition Language,namespace和table的增删改,column familiy的增删改等)。
- 管理namespace和table的元数据(实际存储在HDFS上)。
- 权限控制(ACL)。
HRegionServer节点用于:
- 存放和管理本地HRegion。
- 读写HDFS,管理Table中的数据。
- Client直接通过HRegionServer读写数据(从HMaster中获取元数据,找到RowKey所在的HRegion/HRegionServer后)。
ZooKeeper集群是协调系统,用于:
- 存放整个 HBase集群的元数据以及集群的状态信息。
- 实现HMaster主从节点的failover。
HBase Client通过RPC方式和HMaster、HRegionServer通信;一个HRegionServer可以存放1000个HRegion;底层Table数据存储于HDFS中,而HRegion所处理的数据尽量和数据所在的DataNode在一起,实现数据的本地化;数据本地化并不是总能实现,比如在HRegion移动(如因Split)时,需要等下一次Compact才能继续回到本地化。
1.1 数据读写流程
读:
1. 客户端通过zookeeper以及root表和meta表找到目标数据所在的regionserver
2. 联系regionserver查询目标数据
3. regionserver定位到目标数据所在的region,发出查询请求
4. region先在memstore中查找,命中则返回
5. 如果在memstore中找不到,则在storefile中扫描(可能会扫描到很多的storefile----bloomfilter)
写:
1. client向region server提交写请求
2. region server找到目标region
3. region检查数据是否与schema一致
4. 如果客户端没有指定版本,则获取当前系统时间作为数据版本
5. 将更新写入WAL log
6. 将更新写入Memstore
7. 判断Memstore的是否需要flush为Store文件。
细节描述:
hbase使用MemStore和StoreFile存储对表的更新。
数据在更新时首先写入Log(WAL log)和内存(MemStore)中,MemStore中的数据是排序的,当MemStore累计到一定阈值时,就会创建一个新的MemStore,并 且将老的MemStore添加到flush队列,由单独的线程flush到磁盘上,成为一个StoreFile。于此同时,系统会在zookeeper中记录一个redo point,表示这个时刻之前的变更已经持久化了。
当系统出现意外时,可能导致内存(MemStore)中的数据丢失,此时使用Log(WAL log)来恢复checkpoint之后的数据。
StoreFile是只读的,一旦创建后就不可以再修改。因此Hbase的更新其实是不断追加的操作。当一个Store中的StoreFile达到一定的阈值后,就会进行一次合并(minor_compact, major_compact),将对同一个key的修改合并到一起,形成一个大的StoreFile,当StoreFile的大小达到一定阈值后,又会对 StoreFile进行split,等分为两个StoreFile。
由于对表的更新是不断追加的,compact时,需要访问Store中全部的 StoreFile和MemStore,将他们按row key进行合并,由于StoreFile和MemStore都是经过排序的,并且StoreFile带有内存中索引,合并的过程还是比较快。
1.2 概述
1.2.1 NoSQL
HBase 是大型分布式数据库。 技术上来说, HBase 更像是"数据存储(Data Store)" 多于 "数据库(Data Base)"。因为缺少很多RDBMS特性, 如列类型,二级索引,触发器,高级查询语言等。
然而, HBase 有许多特征同时支持线性化和模块化扩充。 HBase 集群通过增加RegionServers进行扩充。 它可以放在普通的服务器中。例如,如果集群从10个扩充到20个RegionServer,存储空间和处理容量都同时翻倍。 RDBMS 也能很好扩充, 但仅对一个点 - 特别是对一个单独数据库服务器的大小 - 同时,为了更好的性能,需要特殊的硬件和存储设备。
1.2.2 使用场景
HBase不适合所有问题。
首先,确信有足够多数据,如果有上亿或上千亿行数据,HBase是很好的选择。 如果只有上千或上百万行,则用传统的RDBMS可能是更好的选择。因为所有数据可以在一两个节点保存,集群其他节点可能闲置。
其次,确定可以不依赖所有RDBMS的额外特性 (e.g., 列数据类型, 二级索引, 事物,高级查询语言等.) 一个建立在RDBMS上应用,如不能仅通过改变一个JDBC驱动而搬到到Hbase上。 需考虑这个操作从RDBMS 到 HBase是一次完全的重新设计。
第三, 确定你有足够硬件。甚至 HDFS 在小于5个数据节点时,干不好什么事情 (根据如 HDFS 块复制具有缺省值 3), 还要加上一个 NameNode。
HBase 能在单台笔记本上运行良好。但这应仅当成开发配置。
1.2.3 HBase 和 Hadoop/HDFS 的区别?
HDFS是分布式文件系统,适合保存大文件。官方宣称它并非普通用途文件系统,不提供文件的个别记录的快速查询。 另一方面,HBase基于HDFS且提供大表的记录快速查找(和更新)。这有时可能引起概念混乱。HBase 内部将数据放到索引好的 "存储文件(StoreFiles)" ,以便高速查询。存储文件位于HDFS中。
1.3 目录表
目录表hbase.meta存在于HBase表中,只不过他们被HBase Shell的list命令过滤掉了,但他们和其他的表一样存在。
1.3.1 -ROOT-
-ROOT-表从HBase0.96版本之后就被删除了变为了hbase:meta表。
1.3.2 hbase:meta
hbase:meta保存系统中所有region列表。 hbase:meta表结构如下:
Key:
Region key 格式 ([table],[region start key],[region id])
Values:
info:regioninfo (序列化.META.的 HRegionInfo 实例 )
info:server ( 保存hbase:meta的RegionServer的server:port)
info:serverstartcode ( 保存hbase:meta的RegionServer进程的启动时间)
当表在拆分过程中,会创建额外的两列, info:splitA和info:splitB 代表两个region. 这两列的值同样是序列化HRegionInfo 实例。 region最终拆分完毕后,这行会删除。
HregionInfo要注意: 空 的key 用于指示表的开始和结束。具有从空开始键值的region是表内的首region。 如果 region 同时有空起始和结束key,说明它是表内唯一的region。
1.3.3 启动时序
hbase:meta地址首先在ROOT 中设置。hbase:meta会更新 server 和 startcode 的值。