HBase、Redis中关于“长事务”(Long Transaction)的一点讨论

首先解释下标题,可能命名不是那么严谨吧,大致的定义如下:

sometimes you are in a situation where you want to read a record, check what is in it, and depending on that update the record. The problem is that between the time you read a row and perform the update, someone else might have updated the row, so your update might be based on outdated information.

摘要一下:进程A读取了某行R,进行时间较长的计算操作,在这个计算过程中B对行R进行了更改。A计算完毕后,若直接写入,会覆盖B的修改结果。此时应令A写入失败。

以下的讨论整理自下述两个页面,表示感谢!

http://www.ngdata.com/hbase-row-locks/

http://redis.io/topics/transactions

一个最简单、直接的思路是:Transaction + Row Lock。类似于传统DBMS的思路:首先开启行锁,新建一个Transaction,随后进行各种操作,最后commit,最最后解除行锁。看似很简单,也没什么Bug,但注意,若计算时间较长,整个DB就挂起了,不能执行任何操作。

BigTable的Paper中,对这类问题进行了讨论。

总体来说解决思路有三:

1、Rowlock,但是对于HBase来说,RegionLock更成熟。因为RowLock会长时间(从Transction开始到更新)占用一个线程。当并发量很大的时候,系统会挂掉。。。

2、ICV即HBase的incrementColumnValue()方法。

3、CAS即HBase的checkAndPut方法:在Put之前,先检查某个cell的值是否和value一样,一样再Put。注意,这里检查条件的Cell和要Put的Cell可以是不同的column,甚至是不同的row。。。

综上在HBASE中,使用上述CAS方法是较好的解决方案。

上面说了HBase,再来看一个轻量级的Redis:

Redis也支持事务,具体见:http://redis.io/topics/transactions

通过MULTI开始一个事务,EXEC执行一个事务。在两者之间可以“执行”多个命令,但并未被实际执行,而是被Queue起来,直到EXEC再一起执行。Redis保证:在一个事务EXEC的过程中,不会处理其他任何Client的请求(会被挂起)。注意这里是EXEC锁,而不是整个MULTI锁。所以并发性能还是有保障的。

为了支持Paper中CAS方案,Redis提供了WATCH命令:

So what is WATCH really about? It is a command that will make the EXEC conditional: we are asking Redis to perform the transaction only if no other client modified any of the WATCHed keys. Otherwise the transaction is not entered at all.

已经很显然了,更多具体的,读上述网页的文档吧。

 

 

Leave a Reply

Your email address will not be published.