Redis(八)-事务

1. Redis事务是什么

  • 一次执行多个命令,本质是一组命令的集合。事务中的所有命令都会序列化,按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断

2. 事务相关的命令

  • watch key [key...]:监视一个或多个key。如果在事务执行之前这个或这些key被其他命令锁改动,那么事务会被打断

  • multi:标记一个事务块的开始

  • exec:执行所有事务块内的命令

  • discard:取消事务,放弃执行事务块内的所有命令

  • unwatch:取消watch命令对所有key的监视

3. 事务案例演示

  1. 正常执行
    1
    2
    3
    4
    5
    6
    7
    multi				# 开启事务
    set k1 v1 # 入队
    set k2 v2 # 入队
    get k2 # 入队
    set k3 v3 # 入队
    .... # 入队
    exec # 执行事务
  1. 放弃事务

    1
    2
    3
    4
    5
    6
    7
    multi				# 开启事务
    set k1 v1 # 入队
    set k2 v2 # 入队
    get k2 # 入队
    set k3 v3 # 入队
    .... # 入队
    discard # 放弃事务
  2. 命令语句错误(全体连坐)

    1
    2
    3
    4
    5
    6
    7
    8
    multi
    set k1 v1
    set k2 v2
    get k2
    get set excprisks # 这里会入队错误
    set k5 v5
    ...
    exec

    此时get set excprisks加入队列报错,导致当前事务中全部语句不能被执行

  3. 执行时出错(冤头债主)

    1
    2
    3
    4
    5
    6
    7
    multi
    set k1 v1
    incr k1 # 此时v1为非数字,执行时会出错
    set k2 v2
    get k2
    ...
    exec

    此时incr k1 加入队列成功,只是执行的时候会报错。但是其他命令都会成功执行

由第3、4点得出:Redis的事务是部分支持

4. watch监控

  • 注意:一定是先监控,再开启事务

  • 案例

    • 说明:此时Redis库中已有值balance-100、debt-0

      1
      2
      3
      4
      5
      6
      watch balance          #  此时balance为100,debt为0
      # 假设,这里有其他客户端A将balance修改为200
      multi
      decrby balance 20
      incrby debt 20
      exec

      本次事务执行失败。因为在事务执行之前balance数据已经不是watch时的值。此时,获取到的balance为200。

      如果watch后,数据被人改了,执行unwatch命令,取消对所有key的watch。然后再重新watch,再执行事务。

  • 总结
    watch 类似乐观锁,事务提交时,如果key的值被其他客户端修改了,整个事务队列不会执行。
    通过watch命令在事务之前监控了多个keys,如若在watch之后有任何被监视的key的值发生了变化,exec命令执行的事务都会被放弃,并返回Nullmulti-bulk告诉调用这事务执行失败。

5. Redis事务总结

  • 单独的隔离操作
    事务中所有命令都会序列化,按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 没有隔离级别的概念
    队列中的命令没有提交之前都不会实际的被执行,也就不存在事务内的查询要看到事务里的更新。
  • 不保证原子性
    redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚。
------------- 本文结束  感谢您的阅读 -------------
评论