一条数据的HBase之旅,简明HBase入门教程-Flush与Compaction

Flush与Compaction其实属于Write流程的继续,所以本文应该称之为”Write后传“。在2.0版本中,最主要的变化就是新增了In-memory Flush/Compaction,而DateTieredCompaction并不算2.0新加入的特性,2.0版本在Compaction核心算法方面并没有什么新的突破。本文将带你探讨Flush/Compaction的一些本质问题。

前文回顾

前文《一条数据的HBase之旅,简明HBase入门教程:Write全流程》主要讲了如下内容:

  • 介绍HBase写数据可选接口以及接口定义
  • 通过一个样例,介绍了RowKey定义以及列定义的一些方法,以及如何组装Put对象
  • 数据路由,数据分发、打包,以及Client通过RPC发送写数据请求至RegionServer
  • RegionServer接收数据以后,将数据写到每一个Region中。写数据流程先写WAL再写MemStore,这里展开了一些技术细节
  • 简单介绍了HBase权限控制模型

至此,数据已经被写入WAL与MemStore,可以说数据已经被成功写到HBase中了。事实上,上篇文章讲到的Flush流程是”简化”后的流程,在2.0版本中,这里已经变的更加复杂。

本文思路

  1. 回顾Flush & Compaction旧流程
  2. 介绍2.0版本的In-memory Flush & Compaction特性
  3. 介绍Compaction要解决的本质问题是什么
  4. 在选择合理的Compaction策略之前,用户应该从哪些维度调研自己的业务模型
  5. HBase现有的Compaction策略有哪些,各自的适用场景是什么
  6. Compaction如何选择待合并的文件
  7. 关于Compaction更多的一些思考
  8. 在文末的参考信息部分,列出了与Compaction有关的价值问题单

Flush&Compaction旧流程回顾

这是1.X系列版本以及更早版本中的Flush&Compaction行为:

MemStore中的数据,达到一定的阈值,被Flush成HDFS中的HFile文件。

但随着Flush次数的不断增多,HFile的文件数量也会不断增多,那这会带来什么影响?在HBaseCon 2013大会上,Hontonworks的名为《Compaction Improvements in Apache HBase》的演讲主题中,提到了他们测试过的随着HFile的数量的不断增多对读取时延带来的影响:

ReadLatencyWithoutCompaction

尽管关于Read的流程在后面文章中才会讲到,但下图可以帮助我们简单的理解这其中的原因:

ProblemofReadingFromMoreHFiles

图中说明了从一个文件中指定RowKey为“66660000431^201803011300”的记录,以及从两个文件中读取该行记录的区别,明显,从两个文件中读取,将导致更多的IOPS。这就是HBase Compaction存在的一大初衷,Compaction可以将一些HFile文件合并成较大的HFile文件,也可以把所有的HFile文件合并成一个大的HFile文件,这个过程可以理解为:将多个HFile的“交错无序状态”,变成单个HFile的“有序状态”,降低读取时延。小范围的HFile文件合并,称之为Minor Compaction,一个列族中将所有的HFile文件合并,称之为Major Compaction。除了文件合并范围的不同之外,Major Compaction还会清理一些TTL过期/版本过旧以及被标记删除的数据。下图直观描述了旧版本中的Flush与Compaction流程:

FlushAndCompactionOldFlow

Flush

在2.0版本中,Flush的行为发生了变化,默认的Flush,仅仅是将正在写的MemStore中的数据归档成一个不可变的Segment,而这个Segment依然处于内存中,这就是2.0的新特性:In-memory Flush and Compaction ,而且该特性在2.0版本中已被默认启用(系统表除外)

Update: 该特性因为导致性能明显下降,在正式发布的2.0版本中又被默认禁用了,详情请参考:HBASE-20464。

上文中简单提到了MemStore的核心是一个CellSet,但到了这里,我们可以发现,MemStore的结构其实更加复杂:MemStore由一个可写的Segment,以及一个或多个不可写的Segments构成。

InMemoryFlush

MemStore中的数据先Flush成一个Immutable的Segment,多个Immutable Segments可以在内存中进行Compaction,当达到一定阈值以后才将内存中的数据持久化成HDFS中的HFile文件。

看到这里,可能会有这样的疑问:这样做的好处是什么?为何不直接调大MemStore的Flush Size?

如果MemStore中的数据被直接Flush成HFile,而多个HFile又被Compaction合并成了一个大HFile,随着一次次Compaction发生以后,一条数据往往被重写了多次,这带来显著的IO放大问题,另外,频繁的Compaction对IO资源的抢占,其实也是导致HBase查询时延大毛刺的罪魁祸首之一。而In-memory Flush and Compaction特性可以有力改善这一问题。

那为何不干脆调大MemStore的大小?这里的本质原因在于,ConcurrentSkipListMap在存储的数据量达到一定大小以后,写入性能将会出现显著的恶化。

在融入了In-Memory Flush and Compaction特性之后,Flush与Compaction的整体流程演变为:

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值