面试必备:HBase 最全系统介绍存储原理(二)
问题导读:1、HBase HFile是什么?
2、HFile(StoreFile) 文件有哪些特性?
3、HBase WAL(预写日志)如何理解?
4、HBase数据存取流程是什么?
上一篇:面试必备:HBase 最全系统介绍存储原理(一)
HBase 存储模块
RegionServer 包含多个 Region和 一个 HLog
Region : 也称为 HRegin ,它是存储用户数据的最小单元,它对应一张表的部分行数据。一张HBase 表可能会根据行键分成多段存储在不同的 RegionServer 中的不同 Region 上,以实现负载均衡。
HLog : HLog 文件存储在硬盘上,用于实现 WAL(预写日志)。当用户数据进入到 RegionServer 后最先会被保存在 HLog 中,以实现高可用。当服务当机等情况发生后。可用通过回放日志恢复到之前的状态。
一个 RegionServer 可以包含多个 Region ,一个 Region 又包含多个 store ,store 对应表中的列族,表中有多少个列族, 该表的 Region 中就有多少个 store!
store由一个 MemStore和多个 storeFile组成
MemStore : 它是存储在内存中的数据结构,当用户数据已经保存到 HLog后,数据才会进入到 region ,然后先会刷新到对应 store 的 MemStore中,MemStore达到阈值之后,才会刷新到 storeFile中
storeFile/HFile: storeFile 是 MemStore中数据达到阈值之后刷写出来的文件。存储表数据的文件。storeFile 文件最终会被转换成 HFile 格式存储在 HDFS 上
HLog 和 MemStore共同构成了 HBase 中的 LSM(日志结构合并树) 的第一层,它保证了数据可以快速、可靠的写入HBase
storeFile/HFile共同构成了 HBase 中的 LSM(日志结构合并树) 的第二层,它保证了不可靠数据的持久化存储
HBase region
Region是 HBase分布式存储和负载均衡的最小单元,一个 Regionserver 服务中有多个 Region,每一个 Region 对应一张表的部分行数据(一张表的数据可能会分成多段存储在不同的 RegionServer 中的不同 Region 上)。
当数据不断插入到达 Region 阈值时,Region 会被水平拆分成俩个 Region 。当某一个Region Server 挂掉,或 master 触发负载均衡策略时, Region 可能会从一个 Region Server 移动到另一个 Region Server 上
Region Server 拆分 Region 的过程如下
先将 Region 下线,然后拆分
然后将拆分出来的 Region 的信息加入到元信息表 Mete Table 中
最后上线拆分出来的 Region
每一个 Region 会有三个信息标示自己
tableName : 表名称
startRowKey : 从哪个 RowKey开始
createTime : Region 的创建时间,也是最早的一条数据插入进来的时间。也就是说 Region是按需创建的
Region 特点
Region是 HBase分布式存储和负载均衡的最小单元是 HBase分布式存储和负载均衡的最小单元,但不是存储的最小单元。
Region数据过多会导致数量下降,Region数量太少会影响并行查找速度以及压力不够分散,Region最好不要低于集群中节点的数量
Region的拆分过程是不可见的,因为 master 不会参与
HBase HFile
HBase 将数据以 HFile 文件格式保存咋 HDFS 上
HFile 与其他组件
store、memStore、storeFile 、HFile 之间的关系如下
一个 Region 中可能有多个 store ,每一个 store 代表一个列族,一个 store 有一个 memStore ,它是一个内存型的数据结构,保存用户修改的数据。store 还可能有多个 storeFile ,它是文件系统级别的数据结构。
store 由 Region 管理,用于维护列族数据,Region 中存储的表有一个列族,该 Region 就有几个 store ,HBase 会根据 store 大小去判断是否拆分
region
memStore 默认大小为 64 MB ,当数据满后,HBase 会将 memStore 中的数据刷写到 storeFile 中,而 storeFile 底层采用 HFile文件格式存储。
HFile(StoreFile) 文件
StoreFile 以 HFile 格式保存在 HDFS 上。HFile 是 Hadoop 的二进制格式文件。实际上 StoreFile 就是对 HFile 做了轻量级包装,即 StoreFile 底层就是 HFile
HFile 文件是 HBase 最基础的存储单元,它是用户数据的实际载体,它底层是 HDFS 的二进制格式文件,存储着 key - value 格式的数据
HFile 文件结构如上,一共包含4个部分,分别用不同颜色表示
Scanned block section : 在顺序扫描 HFile 的时候,这个部分的数据块会被读取,用户数据存储在其中
Non - scanned block section : 在顺序扫描 HFile 的时候,这个部分的数据块不会被读取,主要包含一些元数据
Load - on - open section : HFile 文件的元数据信息,在 Region Server 启动的时候,会加载到内存中
Trailer : 记录了 HFile 寻址信息、各个部分的偏移量、版本等,目前 HBase 使用的 HFile 是 2.0 版本的
Data Block
用户数据存储在 HFile 文件的 Scanned block section 区域中,具体则是存储在 Scanned block section 的 Data Block中。
Data Block 存储着 key - value 格式的数据
如上图,Data Block 中包含多个 key - value ,每个 key - value 又由4个部分组成
Key Length : key 的长度
Value Length : value 的长度
key : key 由多个信息组成,之后会单独细讲
value : 某张表的某一行的某一个列族中的某个列的数据
Data Block 中 key - value的 key 由多个部分组成
Row Length : 行键的长度
Row : 行键,即 HBase 表的每行数据中的 RowKey
ColumnFamilyLength : 列族名长度
ColumnFamily : 列族名
ColumnQualifierLength : 列标示符长度
ColumnQualifier : 列标示符,即列名称
Timestamp : 这个值的时间戳,也可以理解为这个值的版本号
KeyType : key 的类型,用于给数据做标记,当扫描时,遇到 Delete 标记跳过这条 key - value
Put : 添加数据
Delete : 删除整行
DeleteColumn : 删除整个列族
DeleteFamily : 删除整列
HBase Compaction
在上面的章节中讲到 HBase 采用了 3 层 LSM ,第一次是将数据存入 memStore (内存)中,第二层是将 memStore 中的数据刷写到 StoreFile 文件中,而 HBase Compaction 则承担了 LSM 的第三层,将多个小的 StoreFile 文件合并成一个大的文件。
合并的区域
HBase Compaction 会在特定的时期,合并某个 RegionServer 的某个 Region 的某个 Store 中部分的storeFile文件。也就是说 HBase Compaction 的合并操作不会垮两个 Store。
合并的过程
HBase Compaction 先从这些待合并的文件中读出 key - value ,然后将这些数据重新排序后写入到新的 HFile 中
为什么要设计HBase Compaction
随着系统的运行,文件会越来越多,文件太多,会导致维护困难,而且不利于数据查询,会影响数据查询的效率(因为可能需要打开多个文件才能找到数据,而打开、关闭文件是要消耗系统资源的),因此需要合并
HBase Compaction 在合并过程中会清理三类数据
KeyType 类型为 delete 的数据
ttl 过期的数据
版本过期的数据,比如某张表的最大版本设置为3,当某条数据的第4个版本插入时,最老的第一个版本不会立即删除,而是在合并时才被删除
两种 HBase Compaction
HBase Compaction 分为两种 Minor Compaction (小合并) 和 **major Compaction **(大合并)
Minor Compaction 是选取相邻的 storeFile 合并成一个大的 storeFile
major Compaction 是将 store 中所有的 storeFile 合并成一个大的 storeFile,由于 major Compaction 合并的文件较多,持续的时间较长,整个过程会消耗大量的系统资源,对上层业务会有比较大的影响,因此在生产环境中,一般都会将自动触发的 major Compaction 关掉,改为手动在业务低锋期触发。
Compaction 触发时机
HBase Compaction 触发因素有很多,最常见的因素有三种
MemStoreFlash : 每次 MemStore 数据满了刷写到 HFile 之后,都会对当前 Store 中的文件进行判断,如果文件的数量到达阈值,就会触发 Compaction ,这也是 HBase Compaction 触发的源头
Compaction Check : Compaction Check 线程会在后台周期性的检查,它首先会检查文件数量,当文件的数量到达阈值,就会触发 Compaction ,其次还会检查当前 Store 中 HFile 的最早更新时间早于某个值(这个值我们叫做 MCTime),就会触发 major Compaction
MCTime 是一个浮动值,默认浮动区间为 。
其中 7 是配置项 hbase.hregion.majorcompaction 的值
0.2 是配置项 hbase.hregion.majorcompaction.jitter 的值
默认在 7天左右就会进行一次 major Compaction ,如果想要禁用自动 major Compaction ,只需要将 hbase.hregion.majorcompaction 的值设为 0 即可
手动触发 : 一般手动触发都是执行major Compaction
HBase WAL(预写日志)
HBase WAL 类似于 mysql的 binlog,它记录了所有的数据改动,一旦服务崩溃,可以通过重放 WAL 恢复到崩溃之前的状态。
当对 Regin Server 写入数据的时候,如果写入 WAL 失败,整个操作都会被认为失败的。
如上图,HBase Client 在执行 put、delete等命令时,首先都要记录 log ,然后再到 Region
HBase WAL 为 Hbase 数据提供灾难恢复,提高了数据库的可靠性,同时通过同步日志文件,可以实现远程备份功能
HLog
HBase WAL 机制是通过 Hlog 来实现的,HLog 是 HBase WAL 的具体实现类,并且一个 Regin Server 服务只有一个 HLog 实例。当 Regin 初始化的时候,HLog 实例会当做一个参数传递给Regin的构造函数,这样一来 Regin 就得到了 HLog 的应用,可以实现打日志
出于对性能的考虑,put()、delete()、incr() 有一个开关函数 setReadToWAL(boolean b) ,参数是一个布尔类型,可以设置为 false 来表示是禁用 wal
WAL 使用 Hadoop 的序列化文件,将日志存储为 key - value 格式的数据集 ,其中 value 部分为用户的 put、delete 等操作的数据,key 为 HLogKey,它由以下内容组成
Region : 数据归属的 Region
TableName : 数据归属的表
SequenceNumber : 序列号
WriteTime : 日志写入时间
HLogSyncer
HLogSyncer 是日志同步刷写类,HBase WAL 默认是将日志直接写入文件系统,但有时候为了提高性能,会暂时将日志写入到内存中,这时候就需要用一个异步的线程去实现将内存中的日志数据刷写到文件系统中,HLogSyncer 就是负责这件事。
HLogSyncer 有两种策略
[*] 定时刷写 : 根据设定的时间间隔去刷写
[*] 内存阈值 : 当内存达到阈值时,刷写到文件系统
HLogRoller
HBase Log 文件大小可以通过配置文件设置,默认为 1个小时,也就是说每个小时产生一个新的 log 文件
HLogRoller 后台线程负责整理这些日志文件,它主要有以下功能
在特定的时间滚动日志,形成新的文件,防止单个文件过大
根据 HLog 的 SequenceNumber 对比已经持久化的序列号,删除旧的、不需要的日志
HBase 数据存取流程
存储
客户端
存储数据(Put、Delete)时, HBase Client 的主要流程如下
HBase Client 请求 Zookeeper 获取 HBase Mete Table(元信息表),从 Mete Table 中获取 Region Server 的地址
根据 Region Server 的地址找到 Region Server 服务
获取 Region Server 服务中各 Region 的元信息(Table Name、startRowKey等)
用户提交 Put、Delete 请求时,HBase Client 先将请求放入本地 buffer 中(autoFlash 默认为 true,也可以配置成关闭,关闭后,一次一提交),直到满足阈值条件(默认2M)后,会通过异步批量提交到 HBase 服务端
服务端
存储数据(Put、Delete)时,HBase Server 的主要流程如下
[*]当数据到达Region Server 的某一个Region 后,首先会获取 RowLock(行锁),并创建共享锁。Hbase 通过 RowLock 来保证对一行数据的操作的原子性
[*]将数据写 HLog,注意此时**(持有 RowLock时),并不会将HLog 刷写到硬盘上**。HBase 通过 HLog 实现 WAL 机制
[*]完成写日志后,在按照列族将数据写入到列族对应 Stroe 中的 MenStore 里。先写日志再写缓存,这样即使服务宕机,也可以通过日志恢复
[*]释放 RowLock及共享锁,将 HLog 刷写到硬盘。先释放 RowLock 再刷写 HLog 到硬盘是为了减小持有行锁的时间,提高写性能
[*]如果 HLog 刷写到硬盘失败,执行回滚,将各 MenStore 中的数据删除
[*]当 MenStore 中的数据超过阈值(默认64M),启动异步线程,刷写到硬盘上,形成多个 storeFile
[*]storeFile 数量增长到阈值时,触发 HBase Compaction 将多个 storeFile 合并成一个 storeFile ,同时删除时间过期、版本过期、Delete 标记的数据
[*]经过多轮 HBase Compaction 之后,当单个 storeFile 大小超过阈值时,触发 HBase Split ,将当前 **Region ** 分裂成两个 **Region ** ,并通知 Master 服务。
[*]Master 会下线原来的 **Region ** ,并将新分裂出来的两个 **Region ** 根据负载均衡分配到Region Server 上(可能会分配到不同的Region Server 上)
读取
客户端
HBase Client 读取数据(Scan)时, 除了不会将请求放入本地 buffer 中,其他地方跟存储时,基本一致,不做过多介绍
服务端
读取数据(Scan)时, HBase Client 的主要流程如下
当数据到达Region Server 后,根据 Scan 的内容,HBase 会在 Region Server 的 Region 上构建 Region Scanner
Region Scanner 会根据列族,构建 Store Scanner,负责对 列族的数据检索 (有多少个列族,就会构建多少个 Store Scanner)
每个 Store Scanner 会为当前 Store 中的每个 HFIle 构造一个 Store File Scanner 用于执行实际的文件检索,此外,还会对 Store 中的 Mem Store 构建 Mem Store Scanner 用于检索 Mem Store 中的数据
将 Mem Store Scanner 、Store File Scanner 扫描到的 Key - value 结构的数据封装之后返回给客户端
**HBase ** 读取数据的核心是 3层 Scanner
第一层 : Region Scanner
第二层 : Store Scanner
第三层 : Mem Store Scanner 、Store File Scanner
一个Region Scanner 由多个(列族个)Store Scanner 组成,一个Store Scanner,由多个 Store File Scanner 以及一个Mem Store Scanner组成
作者:我妻礼弥
来源:https://juejin.cn/post/6911885877408956429
最新经典文章,欢迎关注公众号http://www.aboutyun.com/data/attachment/forum/201903/18/215536lzpn7n3u7m7u90vm.jpg
OpenJdk15编译HBase并部署到cdh6.3.2中以应用其ZGC:
https://blog.csdn.net/benpaodexiaowoniu/article/details/114770848 这篇文章写的不错
页:
[1]