一、介绍
如果在HBase中使用某一行的值进行Put操作进行计数器功能,为了保证原子性操作,必然会导致一个客户端对计数器所在行的资源占有,如果在大量进行计数器操作时,则会占有大量资源,并且一旦某一客户端崩溃,将会使得其他客户端进入长时间等待。HBase中定义了一个计数器来完成用户的技术操作,并且防止资源占有问题,并且也保证其原子性。
二、解释
1、创建计数器
在HBase中,HBase将某一列作为计数器来使用,因此创建计数器与创建行是相同的,因此创建计数器时不需要特定的创建流程,因为HBase的列具有动态添加的特性,使得计数器跟列具有相同的特性:动态添加。在第一次使用时计数器(实质为列)隐藏的进行了创建。
2、计数器的增加
计数器增加值是增加一个long值,其增加的值也有负有正,不同的数据进行增加时有不同的效果:
大于0:增加计数器的值
等于0:不更改计数器的值
小于0:减少计数器的值
需要注意的是,计数器的值增加的是一个long类型的整数,而不是一个字符串,有时候增减一个字符串会发现结果值会突然增大很多。
3、Shell使用
HBase shell环境也提供了计数器的操作,其命令结构为: incr <tablename>,<rowkey>,<family:qualifier>,long n
hbase(main):003:0> incr 'test','row-cr','test:incr',1
COUNTER VALUE = 1
0 row(s) in 0.1560 seconds
hbase(main):004:0> incr 'test','row-cr','test:incr',1
COUNTER VALUE = 2
0 row(s) in 0.0080 seconds
在进行完计数器增加后,计数器的值立刻被返回给客户端。
4、单列增加
在HTable客户端中提供了多个对计数器进行增加的API方法,这里先介绍HTable直接对计数器进行增加:
incrementColumnValue(byte[] row,byte[] family, byte[] qualifier,long amount)
incrementColumnValue(byte[] row,byte[] family, byte[] qualifier,long amount,boolean writeToWAL)
incrementColumnValue(byte[] row,byte[] family, byte[] qualifier,long amount,Durability durability)
这三个函数都是直接对表中的某一行数据进行添加,不过后两个函数定义了是否将数据写入到预写日志文件的模式,着三个函数都返回进行增加后的计数器的值。
/**
* @author wozipa
* @Date 2016-3-16 19:13
* @see 测试htable自带的技术及效果
*/
public void singleIncreament()
{
Configuration conf=init();
try {
//创建表连接
HTable table=new HTable(conf,"test");
//进行已经存在的计数器的增加
long incr1=table.incrementColumnValue(Bytes.toBytes("row-cr"),Bytes.toBytes("test"),Bytes.toBytes("incr"),2);
System.out.println(incr1);
//创建新的计数器
long incr22=table.incrementColumnValue(Bytes.toBytes("row-cr"),Bytes.toBytes("test"),Bytes.toBytes("incr2"),10);
System.out.println(incr22);
//
table.close();
} catch (Exception e) {
// TODO: handle exception
}
}
5、多列增加
Htable直接对计数器进行增加的话可能只能增加一行,如果对一行中的多个计数器进行增加则需要多次发送RPC请求,在新版本的HBaseAPI结果中提供了对一行中的多个计数器进行增加的API:
incrementColumnValue(Increment increment)
/**
* @author wozipa
* @Date 2016-3-16 19:25
* @see 使用Increment对象进行单行多列的计数器增加
*/
public void mutilIncreament()
{
Configuration conf=init();
try {
HTable table=new HTable(conf,"test");
Increment increment=new Increment(Bytes.toBytes("row-rc"));
increment.addColumn(Bytes.toBytes("test"),Bytes.toBytes("incr"),6);
increment.addColumn(Bytes.toBytes("test"),Bytes.toBytes("incr2"),10);
Result result=table.increment(increment);
//对该行数据进行展示
KeyValue[] kvs=result.raw();
for(KeyValue kv:kvs)
{
System.out.println(kv.toString());
System.out.println(Bytes.toString(kv.getValue()));
}
table.close();
} catch (Exception e) {
// TODO: handle exception
}
}
Increament的使用方法和Put、Get等方法是相似的,并且返回一个result对象将整行数据进行返回。
Increment对象也提供了很多方法进行设置:
(1)setWriteToWAL(boolean write)
是否将该操作写入到预先日志HLog中
(2)setDurability(Durability
设置读写日志写入的模式。
(3)setReturnResults(boolean returnResults)
是否将计数器结果值进行返回。
Increment对象还提供了其他方法,这里不再进行详细的解释了,可以通过API文档进行详细的查看。
三、总结
在HBase中,用户可以使用HBase自己提供的计数器进行操作,这样可以提高效率和稳定性。