Redis事务
事务的本质:
- 事务是一个单独的隔离操作:事务是一组命令的集合,事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
- 事务没有隔离级别的概念:所有命令在事务中,在事务队列没有执行之前,并没有被直接执行;
- 事务不保证原子性:redis的单条命令是原子性的,但是事务不保证原子性,在同一事务中假如有一条命令执行失败,其它命令依旧会被执行;
事务能做什么: 一个队列中,一次性、顺序性、排他性的执行一系列命令;
命令:
- multi 开启事务
- exec 执行事务
- discard 放弃执行事务
正常执行一个事务; 示例:
127.0.0.1:6379> multi #开启事务
OK
# 命令入队
127.0.0.1:6379> set k v
QUEUED
127.0.0.1:6379> set kk vv
QUEUED
127.0.0.1:6379> set kkk vvv
QUEUED
127.0.0.1:6379> get kk
QUEUED
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
QUEUED
127.0.0.1:6379> append kkk aaa
QUEUED
127.0.0.1:6379> getrange kkk 0 4
QUEUED
127.0.0.1:6379> setrange kkk 0 ssss
QUEUED
127.0.0.1:6379> exec #执行事务
1) OK
2) OK
3) OK
4) "vv"
5) OK
6) (integer) 6
7) "vvvaa"
8) (integer) 6
放弃执行事务;示例:
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> mset a a b b c c
QUEUED
127.0.0.1:6379> discard #放弃事务
OK
127.0.0.1:6379> get a
(nil)
编译时异常(命令有错误) ,事务中所有的命令都不会被执行;示例:
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k1
QUEUED
# 命令存在错误
127.0.0.1:6379> move k1
(error) ERR wrong number of arguments for 'move' command
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec #执行事务
(error) EXECABORT Transaction discarded because of previous errors.
#执行后抛出异常,该事务中所有命令均未执行
127.0.0.1:6379> get k3
(nil)
运行时异常 ,如果事务中存在语法性问题,执行命令时,错误命令抛出异常,其他正确的命令正常执行;示例:
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set k1 hello
OK
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec #执行事务
#语法有问题的命令执行后抛出异常,其它事务正常执行
1) (error) ERR value is not an integer or out of range
2) OK
3) OK
4) "v2"
127.0.0.1:6379> get k3
"v3"
为什么 Redis 不支持回滚(roll back)
- Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
- 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。