微信登录

事务 - multi

事务 - multi

事务 - multi

命令英文 命令中文 成功 失败 解释
multi 开启事务 OK
set/get… 各种命令 全都返回"QUEUED" 整个事务取消,但不会回滚之前的命令
watch key 监视 exec成功 exec失败 watch到exec这段时间值被其他客户端改了exec就错误
exec 执行事务 返回所有的结果 (nil)
discard 取消事务
  1. Redis 作者认为发生事务回滚的原因大部分都是程序错误导致,这种情况一般发生在开发和测试阶段,而生产环境很少出现。
  2. 对于逻辑性错误,比如本来应该把一个数加 1 ,但是程序逻辑写成了加 2,那么这种错误也是无法通过事务回滚来进行解决的。
  3. Redis 追求的是简单高效,而传统事务的实现相对比较复杂,这和 Redis 的设计思想相违背。

总结:redis不会错,错了就是你的错,我就这样

  1. C - 一致性
  2. 一致性指的就是事务执行前后的数据符合数据库的定义和要求。这一点 Redis 中的事务是符合要求的,上面讲述原子性的时候已经提到,不论是发生语法错误还是运行时错误,错误的命令均不会被执行。
  3. I - 隔离性
  4. 事务中的所有命令都会按顺序执行,在执行 Redis 事务的过程中,另一个客户端发出的请求不可能被服务,这保证了命令是作为单独的独立操作执行的。所以 Redis 当中的事务是符合隔离性要求的。
  5. D - 持久性
  6. 如果 Redis 当中没有被开启持久化,那么就是纯内存运行的,一旦重启,所有数据都会丢失,此时可以认为 Redis 不具备事务的持久性;而如果 Redis 开启了持久化,那么可以认为 Redis 在特定条件下是具备持久性的。

源码

  1. Redis 中每个客户端都有记录当前客户端的事务状态 multiState,下面就是一个客户端 client 的数据结构定义:
  2. typedef struct client {
  3. uint64_t id;//客户端唯一 id
  4. multiState mstate; //MULTI 和 EXEC 状态(即事务状态)
  5. //...省略其他属性
  6. } client;
  7. multiState 数据结构定义如下:
  8. typedef struct multiState {
  9. multiCmd *commands;//存储命令的 FIFO 队列
  10. int count;//命令总数
  11. //...省略了其他属性
  12. } multiState;
  13. multiCmd 是一个队列,用来接收并存储开启事务之后发送的命令,其数据结构定义如下:
  14. typedef struct multiCmd {
  15. robj **argv;//用来存储参数的数组
  16. int argc;//参数的数量
  17. struct redisCommand *cmd;//命令指针
  18. } multiCmd;
事务 - multi