0%

HBase 写 WAL 先还是 Memestore ?

HBase 先写 WAL 先还是 Memestore ?


前言

第一次遇到这个问题时是刚学HBase时,阅读范欣欣老师的《HBase - 数据写入流程解析》文章的评论看到的。

后续又跟同事讨论过这个问题。在这里记录下理清楚的思路。

解释

《一条数据的HBase之旅,简明HBase入门教程-Write全流程》找到了相应解释。

  • 在0.94版本之前,Region中的写入顺序是先写WAL再写MemStore,这与WAL的定义也相符。

  • 但在0.94版本中,将这两者的顺序颠倒了,当时颠倒的初衷,是为了使得行锁能够在WAL sync之前先释放,从而可以提升针对单行数据的更新性能。详细问题单,请参考HBASE-4528

  • 在2.0版本中,这一行为又被改回去了,原因在于修改了行锁机制以后(下面内容将讲到),发现了一些性能下降,而HBASE-4528中的优化却无法再发挥作用,详情请参考HBASE-15158。改动之后的逻辑也更简洁了。

这里说2.x版本又改回去了的原因只是因为之前性能下降,但是没有说为什么性能下降,改回去怎么提升了性能。我还是一脸懵逼。带着打破砂锅问到底的心态,我去翻了翻HBASE-15158

issues 给的解释原文: The old ordering was put in place because it got better performance in a time when WAL was different and before row locks were read/write (HBASE-12751).

渣英语,翻译过来旧方式(即先写WAL再写MemStore)之所以被采用,是因为它在WAL不同的时候以及在读/写行锁之前获得了更好的性能。

官方有做相应的性能测试HBASE-15046

通读下来,我理解是采用旧方式提升了 CAS 接口的吞吐,同时性能测试上显示没有降低,反而提高。

为什么提升了CAS吞吐?

先来看看 CAS 接口概述,《HBase客户端避坑指南》的第2部分有介绍,自行阅读。

就是因为 branch-1 的 HBase 写入操作的顺序导致 CAS 接口是 Region 级别的串行执行,如果不串行执行(即 CAS 运行步骤第 2 步),客户端B可以在客户端A释放行锁,但没有推进 MVCC 的情况下,拿到相同行,然后更新。客户端认为更新两次,但是服务端只执行了一次。所以因为这个设计,所以强制 CAS 是 Region 级别的串行,就算更新不同行也是串行的,极度影响性能。

HBase 2.x 调整了顺序。这样对同一个 Region 内的不同行可以并行执行 CAS,大大提高了 Region 内的 CAS 吞吐。