欢迎投稿

今日深度:

[hbase]Increment V.S. Read-Modify-Write in HBase,

[hbase]Increment V.S. Read-Modify-Write in HBase,


Increment V.S. Read-Modify-Write in HBase

在 HBase: The Definitive Guide 中, Lars George 介绍了 HBase 的一个新特性 Counter Increment,即把一个 column 当作 一个 counter,这样便于给某些应用提供统计功能。

传统上,如果没有 counter,当我们要给一个 column 的值 +1 或者其他数值时,就需要先从该 column 读取值,然后在客户端修改值,最后写回给 Region Server,即一个 Read-Modify-Write (RMW) 操作。在这样的过程中,按照 Lars 的描述1,还需要对操作所在的 row 事先加锁,事后解锁。这会引起许多 contention,以及随之而来的很多问题。而 HBase 的 increment 接口就保证在 Region Server 端原子性的完成一个客户端请求。

至于 increment 的性能如何,我们只有做测试才能知道。YCSB 已经提供了 Read-Modify-Write 的测试接口,而 increment 接口需要自己完成2

然后新建 YCSB 的 workload 配置文件:

recordcount=12000
operationcount=12000000
workload=com.yahoo.ycsb.workloads.CoreWorkload
readallfields=false
incrementproportion=1
readproportion=0
updateproportion=0
scanproportion=0
insertproportion=0
requestdistribution=zipfan

recordcount=12000
operationcount=12000000
workload=com.yahoo.ycsb.workloads.CoreWorkload
readallfields=false
readproportion=0
updateproportion=0
scanproportion=0
insertproportion=0
readmodifywriteproportion=1
requestdistribution=zipfan

测试放在集群上进行:1台 master,6台 regionserver,独立的 zookeeper 集群;底层 HDFS 与 HBase 重叠。当前每个 Region Server 负责 255 左右的 region。YCSB 在另一台机器上,开 120 个线程。测试结果如下。

首先看 throughput:

测试图说明测试的时间基本上已经足够长,性能的波动也有反映出来。RMW 虽然波动较大,但总体性能居然优于 Increment,这是比较意外的事情。而 Increment 的表现非常稳定。从箱线图的角度来看也一致。Latency 的情况类似。

最后对测试结果做下简单的分析。出乎意料,RMW 没有想象的那么差,不过中间波动的情况值得深究一下;Increment 的平均 latency 在 10ms 左右,比 RMW 的 15ms 要好,而且几乎没有性能波动现象。

仔细分析 YCSB 的 RMW 操作的代码,它其实只是简单的将 read() 和 update() 封装起来3

513
514
515
db.read(table,keyname,fields,new HashMap<String,String>());

db.update(table,keyname,values);

它并没有对所操作的 row 进行加锁、解锁操作,而是简单的读取改写。这在 counter 的应用场景中是不可接受的。不加锁在大并发情况下,很容易导致 counter 的值与预期不符。

继续修改 YCSB,由发起请求的客户端对相应的 row 加锁4。之后再进行 Increment 与 RMW 之间的性能比较。

可以预期的是新的 RMW 的性能会非常的差。这里给个测试结果的片段:

200 sec: 15818 operations; 91.3 current ops/sec; [RMW AverageLatency(ms)=2903.83]
210 sec: 15818 operations; 0 current ops/sec;
220 sec: 15818 operations; 0 current ops/sec;
230 sec: 16880 operations; 106.2 current ops/sec; [RMW AverageLatency(ms)=3136.13]
240 sec: 16880 operations; 0 current ops/sec;
250 sec: 16880 operations; 0 current ops/sec;
260 sec: 17747 operations; 86.69 current ops/sec; [RMW AverageLatency(ms)=4262.21]
270 sec: 17747 operations; 0 current ops/sec;
280 sec: 17747 operations; 0 current ops/sec;
290 sec: 18412 operations; 66.5 current ops/sec; [RMW AverageLatency(ms)=5508.39]

在这里修改 RMW 中的关键代码在于:

1
2
3
4
            lock = _hTable.lockRow(Bytes.toBytes(key));
            r = _hTable.get(g);
            _hTable.put(p);
            _hTable.unlockRow(lock);

即在读之前先加锁,写之后放锁。之前的 RMW 的瓶颈在 Read 操作,并且 put 操作可以在 server 端批处理;而这里,锁的引入导致线程间的 contention 陡增。也就是说,线程数量的增加不一定会带来性能的提升,可能反而使性能变差。我们可以以线程数为变量做些测试(以 100s 为限)。

可以看到当线程数超过 16 之后,throughput 反而稍微变差了,更糟糕的是,latency 大幅度的提升。当线程数定在 128 时,情况就变的非常糟糕:latency 基本上是几秒,或者 NA;而 throughput 只能维持在 200 左右。这验证了之前的想法。

所以 HBase 引入 Increment/Counter 是非常重要的,对某些需要原子性更改操作的应用来说则是“致命”的。除了单个 increment 的接口 incrementColumnValue() 外,还有批量 increment 的接口 increment(Increment),方便客户端调用。

除此之外,HBase 还在进行 Coprocessor 的开发,使计算直接在 Region Server 上进行,省去了繁琐耗时的数据移动。


09. December 2011 by marcus
Categories: Programming |Tags: HBase, increment, YCSB |Comments Off

www.htsjk.Com true http://www.htsjk.com/hbase/38824.html NewsArticle [hbase]Increment V.S. Read-Modify-Write in HBase, Increment V.S. Read-Modify-Write in HBase 在 HBase: The Definitive Guide 中,Lars George 介绍了 HBase 的一个新特性 Counter Increment,即把一个 column 当作 一个 counter,...
相关文章
    暂无相关文章
评论暂时关闭