HBase计数器Increment

在互联网企业中,经常会有这样的一些需求,比如说:统计下某网站某日pv/uv量或是统计下某签约作者某篇文章的所获点赞数等等。

传统的做法可能需要我们先读出该列的原有值,然后+1后再覆盖原有值,同时还要加锁处理等等。

为了保证原子性的完成一个客户端请求,HBase 引入了计数器的概念,可以用于实时统计。HBase 有一种机制可以将列当作计数器,支持原子操作。

通过HBase Shell命令使用计数器

HBase计数器就是一个与其他列类似的简单列,列值要求必须以长整型转码插入。计数器不需要初始化,创建一个新列时初始值为0,第一次 incr 操作返回1。

计数器使用 incr 命令,增量可以是正数也可以是负数,但是必须是Long型。其语法如下:

incr '<table>','<row>','<column>',['<increment-value>']

例如,创建计数器并插入值:(注意:步长值可为正、可为负、可为0)

hbase> create 'test','f'
hbase> incr 'test','r1','f:count',1
hbase> incr 'test','r1','f:count',2
hbase> incr 'test','r1','f:count',-1

下面获取计数器值:

hbase> get_counter 'test','r1','f:count'

需要注意的是,增加的参数必须是长整型 Long,如果按照错误的格式更新了计数器(如字符串格式),下次调用 incr 会得到错误的结果。

通过Java API使用计数器

HBase Client API 提供了专门的方法实现对计数器的读取和修改操作,在单独的一次客户端调用中保证原子性。

单计数器 Java API

操作一个计数器,类似 shell 命令 incr。示例代码如下:

HTable table  = new HTable(conf, "counters");

long cnt1 = table.incrementColumnValue(Bytes.toBytes("r1"),Bytes.toBytes("f"),Bytes.toBytes("count"),1L);

多计数器 Java API

使用 Table 的 increment() 方法可以操作一行的多个计数器。需要构建 Increment 实例,并且指定行键:

HTable table  = new HTable(conf, "counters");

Increment incr1 = new Increment(Bytes.toBytes("r1"));
incr1.addColumn(Bytes.toBytes("f"), Bytes.toBytes("count"),1);
incr1.addColumn(Bytes.toBytes("f"), Bytes.toBytes("hits"), 1);

Result result = table.increment(incr1);
for(Cell cell : result.rawCells()) {
    // ...
}

《Flink原理深入与编程实战》