Redis事务(transactions)
可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入。用来一次性、顺序性、排他性的执行一系列命令。
1. Redis事务和数据库事务区别
序号 | 数据库事务 | Redis事务 |
---|---|---|
1 | 单独的隔离操作 | Redis的事务仅仅是保证事务里的操作会被连续独占的执行, redis命令执行是单线程架构,在执行完事务内所有指令前是 不可能再去同时执行其他客户端的请求的 |
2 | 没有隔离级别的概念 | 因为事务提交前任何指令都不会被实际执行,也就不存在 "事务内的查询要看到事务里的更新,在事务外查询不能看到"这种问题了 |
3 | 不保证原子性⚛️ | Redis的事务不保证原子性,也就是不保证所有指令同时成功或 同时失败,只有决定是否开始执行全部指令的能力,没有执行到一半 进行回滚的能力 |
4 | 排它性 | Redis会保证一个事务内的命令依次执行,而不会被其它命令插入 |
2. Redis事务相关命令
2.1 MULTI命令
语法: MULTI
用于标记一个事务块的开始。事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由EXEC
命令原子性(atomic)地执行。
2.2 EXEC命令
语法: EXEC
用于执行事务队列内的所有命令。假如某个(或某些) key正处于WATCH
命令的监视之下,且事务块中有和这个(或这些)key相关的命令,那么EXEC
命令只在这个(或这些)key没有被其他命令所改动的情况下执行并生效,否则该事务被打断(abort)。
2.3 DISCARD命令
语法: DISCARD
取消事务,放弃执行事务队列内的所有命令,恢复连接为非事务模式。如果正在使用WATCH
命令监视某个(或某些) key,那么会取消所有监视,等同于执行命令UNWATCH
。
2.4 WATCH命令
语法: WATCH key [key ...]
用于标记要监视的key,以便有条件地执行事务。WATCH
命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行成功。监控一直持续到EXEC
命令(事务中的命令是在EXEC
之后才执行的,所以在MULTI
命令后可以修改WATCH
监控的键值),WATCH
命令是一种乐观锁🔏的实现。
2.5 UNWATCH命令
语法: UNWATCH
用于取消WATCH
命令对所有key的监视。如果执行过EXEC
或DISCARD
,无需再执行UNWATCH
。因为EXEC
命令执行默认就取消所有对key的监视;而DISCARD
命令在取消事务的同时也会取消所有对key的监视,因此这两个命令执行之后,就没有必要执行UNWATCH
了。
3. 事务相关命令组合使用
Redis使用MULTI
命令标记事务开始,它总是返回OK。MULTI
执行之后,客户端可以发送多条命令,Redis会把这些命令保存在队列当中,而不是立刻执行这些命令。所有的命令会在调用EXEC
命令之后执行。
如果不调用EXEC
,调用DISCARD
会清空事务队列并退出事务。
当Redis连接执行MULTI
命令后,之后所有的命令返回字符串QUEUED
。
3.1 正常顺利执行
multi
命令和exec
命令组合使用
192.168.101.105:6379> multi
OK
192.168.101.105:6379(TX)> set k1 v11
QUEUED
192.168.101.105:6379(TX)> set k2 v22
QUEUED
192.168.101.105:6379(TX)> lpush mylist a b c d e f
QUEUED
192.168.101.105:6379(TX)> exec
1) OK
2) OK
3) (integer) 6
192.168.101.105:6379> lrange mylist 0 -1
1) "f"
2) "e"
3) "d"
4) "c"
5) "b"
6) "a"
3.2 取消执行
multi
命令和discard
命令组合使用
192.168.101.105:6379> multi
OK
192.168.101.105:6379(TX)> hset mymap name jack age 123
QUEUED
192.168.101.105:6379(TX)> zadd zset1 100 jack 80 yuanyuan 82 xiaomi
QUEUED
192.168.101.105:6379(TX)> discard
OK
192.168.101.105:6379> hget mymap name
(nil)
3.3 执行前报错
在调用EXEC
之前出错,命令加入队列失败。例如命令的参数个数不符,或者内存补足。
192.168.101.105:6379> multi
OK
192.168.101.105:6379(TX)> zadd myset 30 jack 40 xiaoli 50 anna
QUEUED
192.168.101.105:6379(TX)> zcount myset
(error) ERR wrong number of arguments for 'zcount' command
192.168.101.105:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
192.168.101.105:6379> zcount myset -inf +inf
(integer) 0
3.4 执行中报错
命令在执行EXEC
之后失败,例如对错误值类型的key执行操作(像在字符串值上执行列表操作)。
192.168.101.105:6379> multi
OK
192.168.101.105:6379(TX)> setbit user_sign_log:001 0 0
QUEUED
192.168.101.105:6379(TX)> setbit user_sign_log:001 3 1
QUEUED
## bitmap类型数据只能存储0和1
192.168.101.105:6379(TX)> setbit user_sign_log:001 2 123
QUEUED
192.168.101.105:6379(TX)> getbit user_sign_log:001 3
QUEUED
192.168.101.105:6379(TX)> exec
1) (integer) 0
2) (integer) 0
3) (error) ERR bit is not an integer or out of range
4) (integer) 1
3.5 watch和unwatch命令使用
WATCH
用于为 Redis事务提供检查和设置(CAS)行为。WATCH
、MULTI
和EXEC
组合使用,Redis在修改的时候会检测数据是否被更改,如果更改了,则执行失败,返回nil。如果key数据已经被修改,执行unwatch
命令提前结束对key的监控。
## 命令行窗口1
192.168.101.105:6379> watch k1
OK
192.168.101.105:6379> get k1
"v11"
192.168.101.105:6379> multi
OK
192.168.101.105:6379(TX)> set k1 v111
QUEUED
## 命令行窗口2
[root@hadoop105 bin]# ./redis-cli -a jack
## 抢先执行同一数据操作
127.0.0.1:6379> set k1 vvvv
OK
## 命令行窗口1
192.168.101.105:6379(TX)> exec
(nil)
192.168.101.105:6379> get k1
"vvvv"