redis中的事务
2015-11-29 21:22
651 查看
本篇博客来讨论redis的事务。redis通过MULTI,EXEC,DISCARD以及WATCH命令来实现事务机制的。
事务中的所有命令,要么依次全部执行,要么都不执行。
在执行事务中的命令时,来自其它客户端的命令不会穿插执行。redis的事务是原子级的,支持并发的。
来看一些示例代码
只要事务中包含一个语法错误的命令,所有的命令都不会执行。再来看第二种情况
我们可以看到,
事务中的错误,几乎都会出现在开发中,而不是生产中,所以,这些错误都会在开发调试的过程中被程序员修复。即便有些错误带到了生产中,回滚并不能弥补程序员的错误。
redis更加重视简单性和性能。
WATCH命令的原理是,监控一个或多个键,如果有任何一个被监控的键发生了变化,则EXEC命令失败。
我们来看下面的示例代码(伪代码)
如果有多个客户端同时执行上面的代码,只有一个EXEC命令能够执行成功,因为MULTI…EXEC..属于事务,多个客户端不可能同时执行事务,肯定有一个先后顺序,当第一个事务的EXEC命令执行成功后,mykey就被修改了,其它事务的EXEC命令就会返回错误,所以,上面的代码是支持并发的。
当EXEC命令执行后,不管成功与否,被监控的键都会释放监控。也可以通过UNWATCH命令来手动解除对某个键的监控。
MULTI…EXEC
redis客户端通过MULTI命令来通知redis服务器即将进入事务模式,redis服务器端返回OK。然后redis客户端开始发送命令,redis服务器接收到命令后,不会立即执行,而是先加入事务队列中并返回QUEUED,当redis客户端发送EXEC命令时,redis开始依次执行事务队列中的所有命令,并依次返回每条命令的结果。redis中的事务可以保证两点:事务中的所有命令,要么依次全部执行,要么都不执行。
在执行事务中的命令时,来自其它客户端的命令不会穿插执行。redis的事务是原子级的,支持并发的。
来看一些示例代码
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SADD set1 a b c QUEUED 127.0.0.1:6379> SADD set1 d QUEUED 127.0.0.1:6379> SADD set1 e QUEUED 127.0.0.1:6379> EXEC 1) (integer) 3 2) (integer) 1 3) (integer) 1 127.0.0.1:6379> SMEMBERS set1 1) "a" 2) "d" 3) "c" 4) "b" 5) "e"
DISCARD命令
redis通过DISCARD命令来清空事务的命令队列并退出事务模式。127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SADD set1 x QUEUED 127.0.0.1:6379> DISCARD OK
事务中的错误处理
在redis的事务中,我们可能会遇到两种类型的错误,第一种是命令的语法错误,redis接收到这种命令后,会直接返回错误信息,并且当发送EXEC命令时,也不会执行其它命令,而是返回错误信息。第二种错误是语法正确,但操作的键的类型不对,redis接收到这种命令后,会返回QUEUED,在执行时,其它的命令正常执行,但这一条错误的命令会返回错误消息。下面我们来做个实验,首先看第一种错误127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SADD set1 x QUEUED 127.0.0.1:6379> SMEMBERS (error) ERR wrong number of arguments for 'smembers' command 127.0.0.1:6379> SMEMBERS set1 QUEUED 127.0.0.1:6379> EXEC (error) EXECABORT Transaction discarded because of previous errors
只要事务中包含一个语法错误的命令,所有的命令都不会执行。再来看第二种情况
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SREM set1 d QUEUED 127.0.0.1:6379> LPUSH set1 d QUEUED 127.0.0.1:6379> SADD set1 m QUEUED 127.0.0.1:6379> EXEC 1) (integer) 1 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 3) (integer) 1 127.0.0.1:6379> SMEMBERS set1 1) "a" 2) "m" 3) "c" 4) "e" 5) "b"
我们可以看到,
LPUSH set1 d这个命令,很显然LPUSH只能对一个列表进行操作,而set1是集合类型,但redis在执行之前并不能分辨出来,所以当时返回的是QUEUED,但是在执行时,还是返回了错误消息。需要注意的是,其它命令都正常执行了。
为什么不支持roll back?
看到这里,如果你有关系型数据库的编程经验的话,你可能会很奇怪,为什么redis不支持回滚操作呢?官方文档的解释大概是这样的:事务中的错误,几乎都会出现在开发中,而不是生产中,所以,这些错误都会在开发调试的过程中被程序员修复。即便有些错误带到了生产中,回滚并不能弥补程序员的错误。
redis更加重视简单性和性能。
WATCH命令
先来考虑一下INCR这个命令,它是先读取(get)一个键的值,然后加一,再存储起来(set)。如果不使用INCR命令而自己实现的话,这个逻辑在并发的条件下可能会出现问题。WATCH命令可以很好地解决这个问题。WATCH命令的原理是,监控一个或多个键,如果有任何一个被监控的键发生了变化,则EXEC命令失败。
我们来看下面的示例代码(伪代码)
WATCH mykey val = GET mykey val = val + 1 MULTI SET mykey $val EXEC
如果有多个客户端同时执行上面的代码,只有一个EXEC命令能够执行成功,因为MULTI…EXEC..属于事务,多个客户端不可能同时执行事务,肯定有一个先后顺序,当第一个事务的EXEC命令执行成功后,mykey就被修改了,其它事务的EXEC命令就会返回错误,所以,上面的代码是支持并发的。
当EXEC命令执行后,不管成功与否,被监控的键都会释放监控。也可以通过UNWATCH命令来手动解除对某个键的监控。
相关文章推荐
- redis安装问题小结
- Redis偶发连接失败案例实战记录
- Redis中实现查找某个值的范围
- Redis和Memcached的区别详解
- 分割超大Redis数据库例子
- Redis总结笔记(一):安装和常用命令
- Redis sort 排序命令详解
- 用Redis实现微博关注关系
- redis中修改配置文件中的端口号 密码方法
- 在Ruby on Rails上使用Redis Store的方法
- SQL Server误区30日谈 第1天 正在运行的事务在服务器故障转移后继续执行
- 浅析SQL Server中包含事务的存储过程
- Mysql中的事务是什么如何使用
- MySql的事务使用与示例详解
- Redis和Memcache的区别总结
- C#分布式事务的超时处理实例分析
- C#中的事务用法实例分析
- 在Node.js应用中使用Redis的方法简介
- Redis服务器的启动过程分析
- web 应用中常用的各种 cache详解