HBase 计数器

Submitted by Lizhe on Wed, 05/03/2017 - 22:37

 

计数器功能可以用来做点击统计,增长的id这类需要每次都保证线程安全的场景

计数器是一类特殊的列, 也挂在列簇下,不过不能使用put去赋值

无论是使用下面哪种方式都只会创建一个带有值的普通列,而不是一个计数器

put 'test','row1','cf:hits','1'

put 'test','row1','cf:hits',1

当尝试使用incr命令来处理上面的方式设置的列值时,会得到如下错误

hbase(main):005:0> incr 'test','row1','cf:hits',1

ERROR: org.apache.hadoop.hbase.DoNotRetryIOException: Field is not a long, it's 1 bytes wide
    at org.apache.hadoop.hbase.regionserver.HRegion.getLongValue(HRegion.java:7705)
    at org.apache.hadoop.hbase.regionserver.HRegion.applyIncrementsToColumnFamily(HRegion.java:7659)
    at org.apache.hadoop.hbase.regionserver.HRegion.doIncrement(HRegion.java:7534)
    at org.apache.hadoop.hbase.regionserver.HRegion.increment(HRegion.java:7494)
    at org.apache.hadoop.hbase.regionserver.RSRpcServices.increment(RSRpcServices.java:554)
    at org.apache.hadoop.hbase.regionserver.RSRpcServices.mutate(RSRpcServices.java:2249)
    at org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:33646)
    at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2188)
    at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:112)
    at org.apache.hadoop.hbase.ipc.RpcExecutor.consumerLoop(RpcExecutor.java:133)
    at org.apache.hadoop.hbase.ipc.RpcExecutor$1.run(RpcExecutor.java:108)
    at java.lang.Thread.run(Thread.java:745)

Here is some help for this command:
Increments a cell 'value' at specified table/row/column coordinates.
To increment a cell value in table 'ns1:t1' or 't1' at row 'r1' under column
'c1' by 1 (can be omitted) or 10 do:

  hbase> incr 'ns1:t1', 'r1', 'c1'
  hbase> incr 't1', 'r1', 'c1'
  hbase> incr 't1', 'r1', 'c1', 1
  hbase> incr 't1', 'r1', 'c1', 10
  hbase> incr 't1', 'r1', 'c1', 10, {ATTRIBUTES=>{'mykey'=>'myvalue'}}
  hbase> incr 't1', 'r1', 'c1', {ATTRIBUTES=>{'mykey'=>'myvalue'}}
  hbase> incr 't1', 'r1', 'c1', 10, {VISIBILITY=>'PRIVATE|SECRET'}

The same commands also can be run on a table reference. Suppose you had a reference
t to table 't1', the corresponding command would be:

  hbase> t.incr 'r1', 'c1'
  hbase> t.incr 'r1', 'c1', 1
  hbase> t.incr 'r1', 'c1', 10, {ATTRIBUTES=>{'mykey'=>'myvalue'}}
  hbase> t.incr 'r1', 'c1', 10, {VISIBILITY=>'PRIVATE|SECRET'}
 

可以使用

delete 'test','row1','cf:hits' 来删除刚才创建的列

hbase(main):011:0> incr 'test','row1','cf:hits',1
COUNTER VALUE = 1
0 row(s) in 0.0060 seconds

hbase(main):012:0> scan 'test'
ROW                                  COLUMN+CELL                                                                                            
 row1                                column=cf:column1, timestamp=1493569173421, value=data1-5                                              
 row1                                column=cf:count, timestamp=1493821414788, value=\x00\x00\x00\x00\x00\x00\x00\x01                       
 row1                                column=cf:hits, timestamp=1493821468123, value=\x00\x00\x00\x00\x00\x00\x00\x01                        
 row2                                column=cf:column2, timestamp=1493124770456, value=data2                                                
 row3                                column=cf:column3, timestamp=1493124770470, value=data3                                                
 row4                                column=cf:column4, timestamp=1493124770474, value=data4                                                
 row5                                column=cf:column5, timestamp=1493124770479, value=data5 

正确获取计数器的方式是使用get_counter而不是get

hbase(main):016:0> get 'test','row1','cf:hits'
COLUMN                               CELL                                                                                                   
 cf:hits                             timestamp=1493821468123, value=\x00\x00\x00\x00\x00\x00\x00\x01                                        
1 row(s) in 0.0390 seconds

hbase(main):017:0> get_counter 'test','row1','cf:hits'
COUNTER VALUE = 1

hbase(main):018:0>