源码之前先了解架构
存储引擎
1,LSM tree
HBase 核心介绍:HBase(PowerSet) 是 Google 的 BigTable 的开源实现,底层存储引擎是基于 LSM-Tree 数据结构设计的。写入数据时会先写 WAL 日志,再将数据写到写缓存 MemStore 中,MemStore 的内部实现是一个跳表数据结构,等写缓存达到一定规模后或满足其他触发条件才会 Flush 刷写到磁盘,为了提高从文件中查找数据的效率,将内存的数据先按照一定的规则排序,然后刷写到磁盘上。这样就将磁盘随机写变成了顺序写,提高了写性能。每一次刷写磁盘都会生成新的 HFile 文件。将一次随机 IO 写入转换成一个顺序 IO 写入(HLog 顺序写入)加上一次内存写入(MemStore 写入),使得写入性能得到极大提升LSM 树的设计思想非常朴素:将对数据的修改增量保持在内存中,达到指定的大小限制后将这些修改操作批量写入磁盘,不过读取的时候稍微麻烦,需要合并磁盘中历史数据和内存中最近修改操作,所以写入性能大大提升,读取时可能需要先看是否命中内存,否则需要访问较多的磁盘文件。极端的说,基于 LSM 树实现的HBase 的写性能比 MySQL 高了一个数量级,读性能低了一个数量级。
2,跳表
对于 HBase 来说,整体的架构设计就是一个 跳表结构,其次,存储在内存中的数据,也是以跳表的数据结构进行存储的!
HBase 的跳表体现在两个方面:HBase 的整体架构HBase 的一张表叫做 HTable,HTable 按照 Rowkey 全局有序,在全表层面,进行范围分区(a-c,c-g,g-h)每一段叫做 Region 就是一个分区每个分区,生成一条索引数据,存储在 meta 表中, meta 当然也有可能变得很大,也需要进行范围分区,也会生成多条元数据每个 meta 的分区的元数据,都存储在 root 表中整体的结构:2 层索引表(meta + root) + 1 层数据(用户表)HBase 的写缓存的数据结构写缓存 MemStore:内部实现就是一个 Map : ConcurrentSkipListMap 基于跳表实现的一种兼顾 查询 和 插入效率的一种数据结构。
3,布隆过滤器
它是由一个很长的二进制向量和一系列随机映射函数组成的一种用来判断元素是否存在的数据结构!内部组成:一个位数组 / 二进制向量 + 一组 Hash 函数, 如果是一个 Hash 函数,其实就是 Hash Table功能:用来快速判断一个元素是否存在于一个庞大的集合内, 常数级别复杂度布隆过滤器的特性:优点:迅速判断一个元素是不是在一个庞大的集合内缺点:有误判,布隆过滤器告诉你的答案,有可能是错的,但是概率非常的低原本不存在于该集合的元素,布隆过滤器有可能会判断说它存在如果布隆过滤器判断说某一个元素不存在该集合,那么该元素就一定不 在该集合内
表模型
4,逻辑模型
在 Google 2006 发表的关于 BigTable 的论文中就提到称 HBase 是:sparse,distributed,persistent、multidimensional sorted map,也就是:HBase 是一个稀疏的、分布式的、多维排序的 Map到底如何理解 HBase 就是一个复杂的 Map 呢?如下说明。
table.get(rowkey) = map(cf, map(qualifier, map(timestamp, value)))
table.get(rowkey, cf) = map(qualifier, map(timestamp, value))
table.get(rowkey, cf, qualifier) = map(timestamp, value)
table.get(rowkey, cf, qualifier, timestamp) = value
所以一个 HBase 其实就可以理解成是如下结构的 Map:
table = map(rowkey, map(cf, map(qualifier, map(timestamp, value))))
table = map((rowkey, cf, qualifier, timestamp), value)
先来看 Map 结构,根据 Key 查询 Value,我们把它称之为 一维表(value = map.get(key))。那么 HBase 就是一张 稀疏的 四维表。维度的概念:可能你还有这种困扰:听人说 HBase 是列式存储?又听人说 HBase 是行式存储?HBase 逻辑上可以看做是列式存储,物理上其实是行式存储,更严谨的说法是列簇式存储。列簇式存储的第一个极端: 每个列簇只有一个列,列式存储,HBase 把每个列簇的数据单独存储列簇式存储的第二个极端:整张表只有一个列簇,包含了所有的列,行式存储来,我们看为何 HBase 是稀疏的四维表:
table.get(rowkey) = map(cf, map(qualifier, map(timestamp, value)))table.get(rowkey, cf) = map(qualifier, map(timestamp, value))
table.get(rowkey, cf, qualifier) = map(timestamp, value)
table.get(rowkey, cf, qualifier, timestamp) = value1234
table = map(rowkey, map(cf, map(qualifier, map(timestamp, value))))
5,物理模型
版本1的:
版本2的:
HFile 中的 Cell 设计:
架构分析
架构:
各大组件的功能:
Client :负责向 ZooKeeper 发起请求,获取元数据维护了一个 MetaCache 用来缓存元数据信息
HMaster:为 HRegionServer 分配 Region负责 HRegionServer 的负载均衡发现失效的
HRegionServer :并重新分配其上的 HRegionHDFS 上的垃圾文件(HBase)回收处理 Schema 更新请求(表的创建,删除,修改,列簇的增加等等 DDL 操作,DML请求由 RegionServer 处理)如果 HBase 的 HMaster 宕机一段时间?HBase 还能正常工作么?
HDFS: 主从架构,namenode死亡,HDFS 集群不可用HBase:主从架构,HMaster死亡,HBase依然可用(DML功能可用,DDL功能不可用)
HRegionServer :HRegionServer 维护 HMaster 分配给它的 Region,处理对这些 Region 的 IO 请求HRegionServer 负责和底层的文件系统 HDFS 的交互,存储数据到 HDFSHRegionServer 负责 Store 中的 HFile 的合并 Compact 工作HRegionServer 负责 Split 在运行过程中变得过大的 Region
ZooKeeper :ZooKeeper 为 HBase 提供 Failover 机制,选举 HMaster,避免单点 HMaster 单点故障问题存储所有 Region 的寻址入口:meta 表在哪台服务器上。实时监控 HRegionServer 的状态,将 HRegionServer 的上线和下线信息实时通知给 HMaster存储 HBase 的 Schema,包括有哪些 Table,每个 Table 有哪些 Column Family
HDFS:负责存储 HBase 的各个 HRegionServer 上生成的 HFile 数据文件负责存储 HBase 的各个 HRegionServer 上生成的 Hlog 日志文件JhY2s,shadow_50,text_Q1NETiBA5rKz5Lic5pmLc3Rhci0xMDI0,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
更详细的架构
寻址机制
在使用 HBase 的时候,不管你做插入,还是查询,你都需要先确定你操作的数据是位于哪个 RegionServer 的 Region 中。这就是 HBase 的寻址。**老版本(0.96x 以前)**三层结构:
新版本:
写流程:
读流程:
道阻且长,加油