1、集群架构
HBase的集群架构主要由以下部分组成
主要有:主节点HMaster和从节点HRegionServer
HMaster
- 主节点,支持单节点、一主一备(active/standby)、一主多备
- 主节点的作用有:
- 管理众多从节点
- 负责HBase的元数据管理
- 负责分配Region到各个从节点
- 保证Region的负载均衡
HRegionServer
- 从节点,一个HBase集群中有多个从节点,一个从节点是由一个HLog和多个Region构成,每个Region是由多个Store模块构成,每个Store模块由一个MemStore和多个storeFile构成
- 从节点的作用有:
- 负责管理Region
- 负责数据的读写
- 负责向主节点汇报元数据信息
对于Region和Store,我们可以具象化的表现为以下图示:
Region
Region是一个逻辑架构,可以理解为一个大的管家,主要负责对表进行水平划分管理,在默认的情况下,一个表只有一个Region
Store
Store也是一个逻辑架构,可以理解为一个小的管家,主要用于对表的垂直分隔,默认情况下一个列族就是一个Store
因此,在一般情况下,我们建议:列族越少越好,原因如下
多个列族会产生多个store,导致一行数据分配在多个内存空间或文件进行存储,在写入数据和读取数据的时候,就会分别获取到多个位置的信息,增加了IO操作,影响了性能。再有,store内部存在flush刷新机制,当Region中的某个store触发了刷新,那么此刻该Region中的其他store也要跟着刷新,导致小文件增加,合并次数也会跟着增加,也极大地影响了性能。
2、读写流程
读取流程
读取流程如下:
- 客户端发起读取数据请求,连接zookeeper
- zookeeper中获取hbase:meta,找到该表放在哪个RegionServer中
- 连接meta表对应的RegionServer,找到要读取的数据在哪个RegionServer的Region中
- 连接对应的RegionServer,从RegionServer中读取Region中的数据
写入流程
写入流程如下:
- 客户端发起写入请求,连接zookeeper
- zookeeper中获取hbase:meta,找到该表放在哪个RegionServer中
- 连接对应RegionServer,查询写入到哪个Region, 这个Region被哪个RegionServer所管理
- 连接对应RegionServer, 开始进行数据写入操作, 写入时, 先将数据写入到这个RegionServer的HLog, 然后将数据写入到对应的Store模块下的MemStore中(可能写入多个MemStore), 当这两个位置都写入成功的时候, 客户端认为数据写入完成了
- 多次上面的操作后,会进入异步操作, 随着客户端不断的写入操作, MemStore中数据会越来越多, 当MemStore的数据达到一定的阈值(128M/1h)后, 就会启动flush刷新线程, 将内存中数据"最终"刷新到HDFS上, 形成一个StoreFile文件
- 随着不断的进行Flush的刷新, 在HDFS上StoreFile文件会越来越多, 当StoreFlie文件达到一定的阈值(3个及以上)后,就会启动compact合并压缩机制, 将多个StoreFlie"最终"合并为一个大的HFile
- 随着不断的合并, HFile文件会越来越大, 当这个大的HFile文件达到一定的阈值("最终"10GB)后,就会触发Split机制, 将大的HFile进行一分为二的操作, 形成两个新的大HFile文件, 此时Region也会进行一分为二,形成两个新的Region, 一个Region管理一个新的大Hfile, 旧的大HFile和对应Region就会被下线
3、核心机制
Flush机制
客户端不断的将数据写入到memstore内存中, 当内存数据达到一定的阈值(128M / 1h)后, 需要将数据刷新到HDFS中,形成一个StoreFile文件。
内部流程:
- 客户端不断向memstore中写入数据, 当memstore中数据达到阈值后, 就会启动Flush操作
- 首先HBase会先关闭掉当前这个已经达到阈值的内存空间, 然后开启一个新的memstore的空间, 继续写入
- 将这个达到阈值的内存空间数据放入到内存队列中, 此队列的特性是只读,在HBase 2.0以上版本中, 可以设置此队列的数据尽可能晚的刷新到HDFS中, 当这个队列中数据达到某个阈值后(内存不足),这个时候触发Flush刷新操作 (希望队列中尽可能多的存储多个memstore的数据, 让更多的数据存储在内存中)
- flush线程会将队列中所有的数据全部读取出来, 然后对数据进行排序合并操作,将合并后数据存储到HDFS中, 形成一个StoreFile的文件
Compact机制
memstore中不断进行ush刷新操作, 就会产生多个storeFile的文件, 当StoreFile的文件达到一定的阈值(达到3个及以上)后, 就会触发compact的合并机制, 将多个storeFile合并为一个大的HFile文件。
compact机制分为两个阶段:minor和major阶段
minor:将多个小的StoreFile(达到三个及以上)合并为一个较大的HFile的操作,此合并过程, 仅仅是将多个合并为一, 对数据进行排序操作, 如果此时数据有过期或者有删除标记数据, 此时不做任何处理的(类似于: 内存中基础型合并方案)。
major:将较大的HFile 和 之前的大HFile进行合并 形成一个更大的HFile文件 (全局合并,默认7天),此合并过程, 会将那些过期的数据, 或者已经标记删除的数据, 在这次合并中, 全部都清理掉
相关配置:
split机制
当StoreFile不断的进行合并操作, 这个大的HFile就会变得越来越大,当这个HFile达到一定阈值(10GB)后, 就会触发Split分裂机制。
公式:min(同个table中在同个region server中的region个数的平方 * 128M(默认值),10GB(默认值))
第一次分裂:
min(1^2 * 128M , 10GB) = 128M 在128M的时候, 就会被触发,触发后, 表的region数量就会变为2个
第二次分裂:
min(2^2 * 128M , 10GB) = 512M 在512M的时候, 就会触发,触发后, 表的region数量会变为 3个
...
直到当region的数量等于9的时候, 计算后 10.125GB ,此时大于10GB ,所以从第九个region开始, 达到10GB才会进行分裂
分裂的作用:
由于表一开始只有一个Region, 也就意味着只有一个RegionServer管理, 如果此时这个表有大量的数据写入和数据读取操作, 就意味这个这些庞大的请求全部打向到同一个RegionServer上, 导致这个RegionServer可能无法承受直接宕机, 而且一旦这个宕机后, 对应Region就会被分配给其他的RegionServer, 然后其他的RegionServer也会跟着一起宕机, 最终导致整个HBase集群从节点全部宕机(雪崩问题)。
而通过快速早的分裂, 可以有多个Region, 有个多个Region后,就可以分布在不同的RegionServer上, 这样当大量的请求过来后, 就可以由多个regionServer一起来承担, 提高并发能力 提高稳定性。