您的位置:首页 > 数据库 > Redis

NoSQL之Redis高级实用命令详解--事务处理

2013-12-05 10:34 861 查看
Redis事务处理

Redis对事务的支持目前还比较简单。Redis只能保证一个client发起的事务中的命令可以连续执行,而中间不会插入其他client的命令。当一个client在一个连接中发出multi命令时,这个连接会进入一个事务上下文,该连接后续的命令不会立即执行,而是先放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令。

1.multi:开启一个事务 exec执行一个事务

我们来看下面的例子:

127.0.0.1:6379> set money 100

OK


127.0.0.1:6379> get money

"100"

127.0.0.1:6379> multi

OK

127.0.0.1:6379> incrby money 150

QUEUED

127.0.0.1:6379> incrby money 150

QUEUED

127.0.0.1:6379> decrby money 100

QUEUED

127.0.0.1:6379> exec

1) (integer) 250

2) (integer) 400

3) (integer) 300

127.0.0.1:6379> get money

"300"


首先我设置money为100,然后用multi开启事务之后的操作就会被queued(放入队列存储),直到执行exec命令之后,队列中的命令一起被执行,money被两次+150然后-100最后结果是300.

注意:如果在multi和exec之间执行了一条错误命令,那么exec执行也不会成功。

127.0.0.1:6379> exec

(error) EXECABORT Transaction discarded because of previous errors.


2.discard:取消一个事务

127.0.0.1:6379> get money

"300"

127.0.0.1:6379> multi

OK

127.0.0.1:6379> set money 200

QUEUED

127.0.0.1:6379> discard

OK

127.0.0.1:6379> exec

(error) ERR EXEC without MULTI

127.0.0.1:6379> get money

"300"


发现事务被取消之后再执行exec,就会告诉你没有事务了。

money还是原来的300没变。

3.redis事务的缺点

127.0.0.1:6379> set name 'test'

OK

127.0.0.1:6379> multi

OK

127.0.0.1:6379> incr money

QUEUED

127.0.0.1:6379> incr name

QUEUED

127.0.0.1:6379> exec

1) (integer) 301

2) (error) ERR value is not an integer or out of range


发现事务并没有回滚,而是把正确的执行了,而错误的没有执行。

这个和第一种说的还不一样,第一步中说的如果你在multi和exec中间执行了一条错误的命令(语法错误),那么整个事务会失败。而如果你没有语法错误,那么就不会回滚,也就失去了事务的真正意义,这是redis对事务处理有待改进的地方。

4.乐观锁复杂事务控制

乐观锁:大多数是基于数据版本(version)的记录机制实现的。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据表添加一个“version”字段来实现取出数据时,将此版本号一同读出,之后更新时,对此版本号+1.此时,将提交数据的版本号与数据表对应记录的当前版本号进行对比,如果提交的数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据。-------svn 的版本控制就是最好的例子

Redis的乐观锁实例:假设有一个money的key,我们开2个session来对money进行赋值操作,我们来看一下结果如何?

Session1:

127.0.0.1:6379> get money

"301"

127.0.0.1:6379> watch money

OK

127.0.0.1:6379> multi

OK

127.0.0.1:6379> incrby money 49

QUEUED


Session2:

127.0.0.1:6379> set money 400

OK

127.0.0.1:6379> get money

"400"


Session1:

127.0.0.1:6379> exec

(nil)

127.0.0.1:6379> get money

"400"


首先我们在session1中开启了对money的监控(watch key开启对key键的监控),然后开启一个事务,把命令incrby money 49放到事务队列中,等待exec执行处理。

之后我们开启session2,在session2中我们直接set money 400,这个时候我们在session2中get一下money发现已经变成400

之后我们回到session1中再用exec去执行事务队列中得incrby money 49这条命令,发现结果是nil也就是没有成功,用get命令看一下money发现是400,而不是449.

整个过程就实现了一个乐观锁。

对watch的特别说明:

watch命令会监听给定的key,当exec的时候如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监听多个key,这样就可以对指定的key加乐观锁了。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然了exec,discard,unwatch命令都会清除连接中的所有监视。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: