
Redis 事务
Redis 中的事务其实是一组命令的集合,命令会被序列化,在事务执行过程中,会按照顺序执行。
一致性、顺序性、排他性的执行一系列的命令
- Redis 中单条命令是保证原子性的,但是 Redis 中的事务不保证原子性
- Redis 事务没有隔离级别的概念,没有关系型数据库中事务隔离级别不同导致的问题(脏读、不可重复读、幽灵)
Redis 的事务:
- 开启事务:
MULTI
- 命令入队:
- 执行事务:
EXEC
,DISCARD
取消事务
使用MULTI
开启事务,然后输入一系列命令入队,EXEC
执行事务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| hominsu-redis-docker:0>MULTI "OK" hominsu-redis-docker:0>SET k1 v1 "QUEUED" hominsu-redis-docker:0>SET k2 v2 "QUEUED" hominsu-redis-docker:0>GET k2 "QUEUED" hominsu-redis-docker:0>SET k3 v3 "QUEUED" hominsu-redis-docker:0>EXEC 1) "OK" 2) "OK" 3) "OK" 4) "OK" 5) "OK" 6) "v2" 7) "OK" 8) "OK" 9) "OK"
|
DISCARD
:取消事务,之前输入的全都不会执行
1 2 3 4 5 6 7 8
| hominsu-redis-docker:0>MULTI "OK" hominsu-redis-docker:0>set k1 v1 "QUEUED" hominsu-redis-docker:0>set k2 v2 "QUEUED" hominsu-redis-docker:0>DISCARD "OK"
|
异常
- 编译型异常,执行不了
- 运行时异常,其他命令都能正常运行,错误命令会抛出异常,不会回滚!!!⚠️
编译型异常,执行事务也是报错的,全部命令都不会被执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| hominsu-redis-docker:0>flushdb "OK" hominsu-redis-docker:0>MULTI "OK" hominsu-redis-docker:0>set k1 v1 "QUEUED" hominsu-redis-docker:0>set k2 v2 "QUEUED" hominsu-redis-docker:0>set k3 "ERR wrong number of arguments for 'set' command" hominsu-redis-docker:0>set k4 v4 "QUEUED" hominsu-redis-docker:0>EXEC "EXECABORT Transaction discarded because of previous errors."
|
运行时错误:中间的 INCR k1
执行会失败,但是其他命令会正常执行,不会回滚
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| hominsu-redis-docker:0>MULTI "OK" hominsu-redis-docker:0>SET k1 "string" "QUEUED" hominsu-redis-docker:0>INCR k1 "QUEUED" hominsu-redis-docker:0>SET k2 v2 "QUEUED" hominsu-redis-docker:0>GET k2 "QUEUED" hominsu-redis-docker:0>EXEC 1) "OK" 2) "OK" 3) "OK" 4) "ERR value is not an integer or out of range" 5) "OK" 6) "OK" 7) "OK" 8) "v2" 9) "OK"
|
监控
悲观锁
乐观锁
- 更新数据的时候判断,在更新期间是否有人修改数据
- 获取 version
- 更新的时候比较 version
WATCH key
:监控一个 key
正常执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| hominsu-redis-docker:0>set money 100 "OK" hominsu-redis-docker:0>set out 0 "OK" hominsu-redis-docker:0>WATCH money "OK" hominsu-redis-docker:0>MULTI "OK" hominsu-redis-docker:0>DECRBY money 20 "QUEUED" hominsu-redis-docker:0>INCRBY out 20 "QUEUED" hominsu-redis-docker:0>EXEC 1) "OK" 2) "80" 3) "OK" 4) "20" 5) "OK"
|
多个线程对数据进行操作:
1 2 3 4 5 6 7 8
| hominsu-redis-docker:0>WATCH money "OK" hominsu-redis-docker:0>MULTI "OK" hominsu-redis-docker:0>DECRBY money 10 "QUEUED" hominsu-redis-docker:0>INCRBY out 10 "QUEUED"
|
- 上面的事务还没有执行的时候,其他线程修改了 money 的值:
1 2 3 4
| hominsu-redis-docker:0>get money "80" hominsu-redis-docker:0>set money 1000 "OK"
|
1
| hominsu-redis-docker:0>EXEC
|
事务执行失败后,Redis 会自动释放锁,执行成功也会执行锁
直接继续进行事务即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| hominsu-redis-docker:0>WATCH money "OK" hominsu-redis-docker:0>MULTI "OK" hominsu-redis-docker:0>DECRBY money 1 "QUEUED" hominsu-redis-docker:0>INCRBY out 1 "QUEUED" hominsu-redis-docker:0>EXEC 1) "OK" 2) "999" 3) "OK" 4) "21" 5) "OK"
|