Redis 事务

分类:生活杂谈
阅读:2658
作者:majingjing
发布:2021-12-13 23:02

Redis 事务

事务相关命令

Multi 命令

Redis Multi 命令用于标记一个事务块的开始。

事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行。

  1. redis 127.0.0.1:6379> MULTI # 标记事务开始
  2. OK
  3. redis 127.0.0.1:6379> INCR user_id # 多条命令按顺序入队
  4. QUEUED
  5. redis 127.0.0.1:6379> INCR user_id
  6. QUEUED
  7. redis 127.0.0.1:6379> INCR user_id
  8. QUEUED
  9. redis 127.0.0.1:6379> PING
  10. QUEUED
  11. redis 127.0.0.1:6379> EXEC # 执行
  12. 1) (integer) 1
  13. 2) (integer) 2
  14. 3) (integer) 3
  15. 4) PONG

Exec 命令

Redis Exec 命令用于执行所有事务块内的命令。

  1. # 事务被成功执行
  2. redis 127.0.0.1:6379> MULTI
  3. OK
  4. redis 127.0.0.1:6379> INCR user_id
  5. QUEUED
  6. redis 127.0.0.1:6379> INCR user_id
  7. QUEUED
  8. redis 127.0.0.1:6379> INCR user_id
  9. QUEUED
  10. redis 127.0.0.1:6379> PING
  11. QUEUED
  12. redis 127.0.0.1:6379> EXEC
  13. 1) (integer) 1
  14. 2) (integer) 2
  15. 3) (integer) 3
  16. 4) PONG
  17. # 监视 key ,且事务成功执行
  18. redis 127.0.0.1:6379> WATCH lock lock_times
  19. OK
  20. redis 127.0.0.1:6379> MULTI
  21. OK
  22. redis 127.0.0.1:6379> SET lock "huangz"
  23. QUEUED
  24. redis 127.0.0.1:6379> INCR lock_times
  25. QUEUED
  26. redis 127.0.0.1:6379> EXEC
  27. 1) OK
  28. 2) (integer) 1
  29. # 监视 key ,且事务被打断
  30. redis 127.0.0.1:6379> WATCH lock lock_times
  31. OK
  32. redis 127.0.0.1:6379> MULTI
  33. OK
  34. redis 127.0.0.1:6379> SET lock "joe" # 就在这时,另一个客户端修改了 lock_times 的值
  35. QUEUED
  36. redis 127.0.0.1:6379> INCR lock_times
  37. QUEUED
  38. redis 127.0.0.1:6379> EXEC # 因为 lock_times 被修改, joe 的事务执行失败
  39. (nil)

Discard 命令

Redis Discard 命令用于取消事务,放弃执行事务块内的所有命令。

  1. redis 127.0.0.1:6379> MULTI
  2. OK
  3. redis 127.0.0.1:6379> PING
  4. QUEUED
  5. redis 127.0.0.1:6379> SET greeting "hello"
  6. QUEUED
  7. redis 127.0.0.1:6379> DISCARD
  8. OK

Watch 命令

Redis Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断

  1. redis> WATCH lock lock_times
  2. OK

Unwatch 命令

Redis Unwatch 命令用于取消 WATCH 命令对所有 key 的监视。

  1. redis 127.0.0.1:6379> WATCH lock lock_times
  2. OK
  3. redis 127.0.0.1:6379> UNWATCH
  4. OK

事务正确理解

代码语法错误, 所有命令不执行

代码语法错误(编译时异常)所有的命令都不执行

  1. > multi
  2. OK
  3. > set k1 v1
  4. QUEUED
  5. > set k2 v2
  6. QUEUED
  7. > error k1 # 这是一条语法错误命令
  8. (error) ERR unknown command `error`, with args beginning with: `k1`, # 会报错但是不影响后续命令入队
  9. > get k2
  10. QUEUED
  11. > EXEC
  12. (error) EXECABORT Transaction discarded because of previous errors. # 执行报错
  13. > get k1
  14. (nil) # 其他命令并没有被执行

代码逻辑错误, 其他命令正常执行

代码逻辑错误 (运行时异常) 其他命令可以正常执行 >>> 所以不保证事务原子性

  1. > multi
  2. OK
  3. > set k1 v1
  4. QUEUED
  5. > set k2 v2
  6. QUEUED
  7. > incr k1 # 这条命令逻辑错误(对字符串进行增量)
  8. QUEUED
  9. > set k2 v22
  10. QUEUED
  11. > get k2
  12. QUEUED
  13. > exec
  14. 1) OK
  15. 2) OK
  16. 3) ERR value is not an integer or out of range # 运行时报错
  17. 4) OK
  18. 5) "v22" # 其他命令正常执行
  19. # 虽然中间有一条命令报错了,但是后面的指令依旧正常执行成功了。
  20. # 所以说Redis单条指令保证原子性,但是Redis事务不能保证原子性。

Redis的单条命令是保证原子性的,但是redis事务不能保证原子性

  • Redis事务没有隔离级别的概念

  • Redis单条命令是保证原子性的,但是事务不保证原子性!

Redis事务本质:一组命令的集合。

————————- 队列 set set set 执行 —————————-

事务中每条命令都会被序列化,执行过程中按顺序执行,不允许其他命令进行干扰。

  • 一次性
  • 顺序性
  • 排他性