HBase
存储机制
RowKey
- 用来表示唯一一行记录的主键
- HBase的数据是按RoeKey的字典顺序进行全局排序的,所有查询都只能依赖于这一排序维度
稀疏矩阵
- HBase中一个表的数据是按稀疏矩阵的方式组织的
- 每一行中列的组成都是灵活的,行与行间不需要遵循相同的列定义
Region
- HBase采用“Range分区”,将Key的完整分区切割为一个个“Key Range”,每一个“Key Range”称为一个Region
- Region是HBase中负载均衡的基本单元,当一个Range增长到一定大小以后会自动分裂为两个
Column Family
- 一个Region列的纵向切割称为一个Column Family
- 每一个列都必须归属于一个Column Family,此归属关系在写数据时指定而不是建表时预先定义
KeyValue
- 每一行的每一列数据都被包装为独立的拥有特定结构的KeyValue,KeyValue中包含了自我描述信息
- 一些Key相同的任意数量的独立KeyValue即可构成一行数据
与RDBMS的区别
HBase | RDBMS |
---|---|
无模式,不具有固定列,仅定义列族 | 有模式,描述表整体结构的约束 |
横向扩展,专门为宽表创建 | 专门为小表创建 |
不存在事务 | 事务性的 |
适用于半结构化及非结构化数据 | 适用于结构化数据 |
只有简单的字符类型 | 有丰富的类型 |
只有简单的插入、查询、删除、清空等操作,表和表之间是分离的 | 通常有各式各样的函数和连接操作 |
基于列存储,每个列族都由几个文件保存,不同列族的文件是分离的 | 基于表格结构和行模式保存的 |
更新操作实际上是插入新的数据 | 更新操作是替换修改 |
能轻松增加或减少硬件的数量,且对错误的兼容性比较高 | 需要增加中间层才能实现类似功能 |
HBase架构
HBase使用MemStore和StoreFile存储对表的更新。数据在更新时首先写入HLog和MemStore。MemStore中的数据是排序的,当MemStore累计到一定阈值时,就会创建一个新的MemStore,并且将老的MemStore添加到Flush队列,由单独的线程Flush到磁盘上,成为一个StoreFile。与此同时,系统会在Zookeeper中记录一个CheckPoint,表示这个时刻之前的数据变更已经持久化了。当系统出现意外时,可能导致MemStore中的数据丢失,此时使用HLog来恢复CheckPoint之后的数据。
StoreFile是只读的,一旦创建后就不可以再修改。因此Hbase的更新其实是不断追加的操作。当一个Store中的StoreFile达到一定阈值后,就会进行一次合并操作,将对同一个key的修改合并到一起,形成一个大的StoreFile。当StoreFile的大小达到一定阈值后,又会对StoreFile进行切分操作,等分为两个StoreFile。
写
- Client通过Zookeeper的调度,向RegionServer发出写数据请求,在Region中写数据
- 数据被写入Region的MemStore,直到MemStore达到预设阈值
- MemStore中的数据被Flush成一个StoreFile
- 随着StoreFile文件的不断增多,当其数量增长到一定阈值后,触发Compact合并操作,将多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除
- StoreFiles通过不断的Compact合并操作,逐步形成越来越大的StoreFile
- 单个StoreFile大小超过一定阈值后,触发Split操作,把当前Region Split成2个新的Region。父Region会下线,新Split出的2个子Region会被HMaster分配到相应的RegionServer上,使得原先1个Region的压力得以分流到2个Region上
读
- Client访问Zookeeper,查找-ROOT-表,获取.META.表信息
- 从.META.表查找,获取存放目标数据的Region信息,从而找到对应的RegionServer
- 通过RegionServer获取需要查找的数据
- Regionserver的内存分为MemStore和BlockCache两部分,MemStore主要用于写数据,BlockCache主要用于读数据。读请求先到MemStore中查数据,查不到就到BlockCache中查,再查不到就会到StoreFile上读,并把读的结果放入BlockCache