HBase
在存储时, 使用了LSM
树来进行数据存储, 会定期将文件进行合并, 以提升数据的查询效率, LSM
树都是这么处理的. 那么到这里就有一个问题了, HBase
在进行文件合并的时候, 势必会占用大量 IO, 难道不会对正常的业务产生影响么? 抱着这个疑问, 我去找了找HBase
文件合并的方式.
在HBase
中, 负责文件合并的模块叫做: 'Compaction'. 分别看了看合并的类型、触发条件、执行过程、优缺点等, 算是简单了解了一下吧.
根据文件合并的规模, 可以分为两种.
「Minor」
规模较小的合并, 选取相邻的几个小的 HFile, 合并成一个更大的 HFile.
Minor
合并的时候, 将多个小文件进行合并, 那么在执行之前, 需要进行待合并文件的选择, 选取的文件一般来说不能太大, 同时也不能太多, 否则会占用过多系统资源. 最好的情况是把文件较小查询较多的文件进行合并, 这样才能达到最好的效果.
「Major」
将一个 store
中的所有HFile 合并为一个大的 HFile.
这里问了, store
是是什么呢? 在HBase
中, 根据row key
, 会将表水平切分为多个 region
, 在每个region
中, 又会根据列族对表进行垂直切分为多个store
.
这里多说一句, 在每个store
中, 并不是所有数据都存在HFile
中, 其中部分数据在内存中, 还没有进行落盘, 所以每个store
由两部分组成: 1. 内存中的有序结构 2. 磁盘中的HFile
同时, 在进行所有文件合并的时候, 还会进行数据清理, 以减少文件占用空间, 清理内容包括:
所以可以通过执行全文件合并来进行存储空间的优化.
文件合并也就意味着需要进行文件的读写以及生成等操作, 势必会占用系统资源及网络带宽(读写要经过 HDFS), 尤其是Major
全文件合并也意味着会占用大量系统资源, 所以在合并过程中, 会对上层业务造成一定的影响.
而合并文件的优点也很明显:
Major
后可以达到100%的本地化. 就剩一个文件了嘛其中优化查询速度是合并文件最主要的目的了.
文件合并虽好, 但也不能一直进行合并, 否则占用太多资源, 根本吃不住来自业务的压力. 那么什么时候会触发文件合并呢?
「1. 文件落盘」
store
中的内存数据进行落盘的时候, 会触发文件合并检查, 当store
下的HFile
数量超过 n
时, 会触发Minor
.
其中数量n
由配置: 「hbase.hstore.compaction.min」
「2. 周期性检查」
有一个线程在后台周期性的进行检查, 会进行一系列检查, 比如文件数量、最早文件的更新时间等. 当符合条件的时候, 就会触发文件合并.
「3. 手动触发」
可以在业务低峰期手动触发Major
来进行优化.
文件合并一般分为以下几步:
store
的数据目录中其中在步骤1和2出错的话, 不用任何处理, 因为数据还没有落盘, 下一次重新合并即可. 在后面出错, 可以根据HLog
继续执行后面的任务.
你要是问我知道这玩意有什么用的话, 我想了想, 唯一的用处就是, 下次如果遇到HBase
占用资源突然剧增的时候, 可以多一个查找的方向吧.