phoenix_行锁

首先hbase有三处与行锁有关:

1. 计数器

用于实时收集信息,原子操作

Shell下操作

incr 't1','20150226','daily:hits',1-- t1 表名

--20150226 行健

-- daily是列族

--hits 是列,最后是值

get_counter 't1','row_key','daily:hits' 

java中操作

1

2

hTable.incrementColumnValue(...)

hTable.increment(increment)

 

2. check

原子插入(compare-and-set

1

hTable.checkAndPut(row,family,qualifier,value,put)

Value为查出来旧值,put中是新值,当修改的时候会再次判断,如果当前记录的此字段值还是旧值则修改,如果不是则返回false

经多线程验证确实如此,如:当前值是100,多线程一个减10,一个减20,由于是高并发,因此两个线程都先查出了原始值为100

然后两个checkAndPut语句分别为:

checkAndPut(row,family,qualifier,100,put-90)

checkAndPut(row,family,qualifier,100,put-80)

先执行的发现目标值为100,因此修改为90成功,后执行的发现目标值为90,但希望旧值为100,因此修改为80失败。

原子删除(compare-and-delete

1

hTable.checkAndDelete(row,family,qualifier,value,delete)

 

3. Lock

http://blog.163.com/liaoxiangui@126/blog/static/7956964020121324644320

https://blog.csdn.net/yfkiss/article/details/36438855

HBase也提供APIlockRow/unlockRow)显示的获取行锁,但不推荐使用。原因是两个客户端很可能在拥有对方请求的锁时,又同时请求对方已拥有的锁,这样便形成了死锁,在锁超时前,两个被阻塞的客户端都会占用一个服务端的处理线程,而服务器线程是非常稀缺的资源。

 

Phoenix

https://www.cnblogs.com/haoxinyue/p/6750078.html

因为如果phoenix有索引表的话,直接操作hbase,不会更新索引表,因此需要通过phoenix来操作。Hbase中的checkAndPut看起来能满足行锁的需求,查资料,在phoenix中对应的是:ON DUPLICATE KEY

ON DUPLICATE KEY这个语法要到Phoenix 4.9之后才有。这个功能把HBaseIncrementCheckAndPut两个原子操作合在了一起。当Upsert语句被提交到服务端的时候,所要更新的行会被lock住,同时相关的列会被读取,ON DUPLICATE KEY语句会被执行。

upsert into "admin"("rowkey","loginTimes")values('83dd751',5)on duplicate key update "loginTimes" = 10

upsert into "admin"("rowkey","loginTimes")values('83dd751',5)on duplicate key update "loginTimes" = "loginTimes" +1

这两行原本以为是如下含义:

对于rowkey'83dd751'的记录,如果loginTimes字段为5就将其设置为10

对于rowkey'83dd751'的记录,如果loginTimes字段为5就将其设置为自身+1

但测试结果让人大跌眼睛:

1. 那个数字5感觉没什么用,不论当前值为多少,都会设置为10(第一条)

2. 既然那个5没什么用,那至少应该能保证原子性吧,即如果来了5个请求,当前值为0的话,每次加1,应该结果值为5才对,不论怎么并发,它都能保证请求是顺序执行,且每次都能用新的值+1.结果并不是。开了4个线程一起跑10次请求,结果很不稳定,一会儿结果不到10,一会又可以达到10以上甚至20.不知道它内部是怎么计算的。

 因此,这算是phoenix的bug,暂时不能用这个方案。

阅读更多
换一批

没有更多推荐了,返回首页