你好,游客 登录
背景:
阅读新闻

HBase Increment(计数器)简介及性能测试

[日期:2013-10-31] 来源:看引擎  作者: [字体: ]

  在 HBase: The Definitive Guide 中, Lars George 介绍了 HBase 的一个新特性 Counter Increment,即把一个 column 当作 一个 counter,这样便于给某些在线应用提供实时统计功能。(PS:比如帖子的实时浏览量:PV)

  传统上,如果没有 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:

  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 中的关键代码在于:

  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 上进行,省去了繁琐耗时的数据移动。(PS:这就是所谓的移动计算比移动数据更划算)

  Tips:以上测试数据由于 Hbase 版本很老,加上作者硬件、集群规模限制,仅供参考~





收藏 推荐 打印 | 录入: | 阅读:
相关新闻      
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款