zoukankan      html  css  js  c++  java
  • Redis的事务

    事务

    MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事务相关的命令。事务可以一次执行多个命令, 并且带有以下两个重要的保证:

    • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

    • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

    EXEC 命令负责触发并执行事务中的所有命令:

      如果客户端在使用 MULTI 开启了一个事务之后,却因为断线而没有成功执行 EXEC ,那么事务中的所有命令都不会被执行。

      另一方面,如果客户端成功在开启事务之后执行 EXEC ,那么事务中的所有命令都会被执行。

    当使用 AOF 方式做持久化的时候, Redis 会使用单个 write(2) 命令将事务写入到磁盘中。

    然而,如果 Redis 服务器因为某些原因被管理员杀死,或者遇上某种硬件故障,那么可能只有部分事务命令会被成功写入到磁盘中。

    如果 Redis 在重新启动时发现 AOF 文件出了这样的问题,那么它会退出,并汇报一个错误。

    使用redis-check-aof程序可以修复这一问题:它会移除 AOF 文件中不完整事务的信息,确保服务器可以顺利启动。

    从 2.2 版本开始,Redis 还可以通过乐观锁(optimistic lock)实现 CAS (check-and-set)操作,具体信息请参考文档的后半部分

    以上摘自官网

    事务到底是什么?

    可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞

    能干嘛

    一个队列中,一次性、顺序性、排他性的执行一系列命令

    操作方法/案例

    • 常用命令

      

    [root@izuf6hmkcpexishpa3id8xz ~]# cd redis-5.0.5
    [root@izuf6hmkcpexishpa3id8xz redis-5.0.5]# src/redis-cli 
    127.0.0.1:6379> ping
    PONG
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set id 12
    QUEUED
    127.0.0.1:6379> get id
    QUEUED
    127.0.0.1:6379> incr t1
    QUEUED
    127.0.0.1:6379> incr t1
    QUEUED
    127.0.0.1:6379> get t1
    QUEUED
    127.0.0.1:6379> EXEC
    1) OK
    3) "12"
    4) (integer) 1
    5) (integer) 2
    6) "2"
    127.0.0.1:6379> 
    • Case2:放弃事务

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set name z3
    QUEUED
    127.0.0.1:6379> set age 28
    QUEUED
    127.0.0.1:6379> incr t1
    QUEUED
    127.0.0.1:6379> discard
    OK
    127.0.0.1:6379> 
    • Case3:全体连坐

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set name z3
    QUEUED
    127.0.0.1:6379> get name 
    QUEUED
    127.0.0.1:6379> incr t1
    QUEUED
    127.0.0.1:6379> get t1
    QUEUED
    127.0.0.1:6379> set email
    (error) ERR wrong number of arguments for 'set' command
    127.0.0.1:6379> EXEC
    (error) EXECABORT Transaction discarded because of previous errors.#一个错误全体连坐,都不执行
    127.0.0.1:6379> 
    • Case4:冤头债主

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set age 11
    QUEUED
    127.0.0.1:6379> incr t1
    QUEUED
    127.0.0.1:6379> set email abc@163.com
    QUEUED
    127.0.0.1:6379> incr email
    QUEUED
    127.0.0.1:6379> get age
    QUEUED
    127.0.0.1:6379> EXEC
    1) OK
    2) (integer) 3
    3) OK
    4) (error) ERR value is not an integer or out of range
    5) "11"
    127.0.0.1:6379> 
    • Case5:watch监控

      1. 悲观锁/乐观锁/CAS(Check And Set)
          • 悲观锁

              悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。

              传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁

             

          • 乐观锁

              乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。

              乐观锁适用于多读的应用类型,这样可以提高吞吐量

              乐观锁策略:提交版本必须大于记录当前版本才能执行更新

          • CAS

                       2.初始化信用卡可用余额和欠额

    127.0.0.1:6379> set balace 100
    OK
    127.0.0.1:6379> set debt 0
    OK
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> DECRBY balace 30
    QUEUED
    127.0.0.1:6379> INCRBY debt 30
    QUEUED
    127.0.0.1:6379> EXEC
    1) (integer) 70
    2) (integer) 30
    127.0.0.1:6379> get balace
    "70"
    127.0.0.1:6379> get debt
    "30"
    127.0.0.1:6379> 

        3.无加塞篡改,先监控再开启multi,保证两笔金额变动在同一个事务内

    127.0.0.1:6379> WATCH balace
    OK
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> DECRBY balace 10
    QUEUED
    127.0.0.1:6379> INCRBY debt 10
    QUEUED
    127.0.0.1:6379> EXEC
    1) (integer) 60
    2) (integer) 40
    127.0.0.1:6379> 

        4.有加塞篡改

          监控了key,如果key被修改了,后面一个事务的执行失效

    127.0.0.1:6379> WATCH balace
    OK
    127.0.0.1:6379> set balace 300 #修改
    OK
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> DECRBY balace 15 #操作
    QUEUED
    127.0.0.1:6379> INCRBY debt 15
    QUEUED
    127.0.0.1:6379> EXEC
    (nil)
    127.0.0.1:6379> get balace #因为改了 所以操作失效
    "300"
    127.0.0.1:6379> 

        5.unwatch

    127.0.0.1:6379> WATCH balace
    OK
    127.0.0.1:6379> set balace 300
    OK
    127.0.0.1:6379> set balace 350
    OK
    127.0.0.1:6379> UNWATCH
    OK
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set balace 100
    QUEUED
    127.0.0.1:6379> set debt 0
    QUEUED
    127.0.0.1:6379> EXEC
    1) OK
    2) OK
    127.0.0.1:6379> get balace
    "100"

        6.一旦执行了exec之前加的监控锁都会被取消掉了

        7.小结

        • Watch指令,类似乐观锁,事务提交时,如果Key的值已被别的客户端改变,
          比如某个list已被别的客户端push/pop过了,整个事务队列都不会被执行

        • 通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,
          EXEC命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失

    • 3阶段

        1.开启:以MULTI开始一个事务

        2.入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面

        3.执行:由EXEC命令触发事务  

    • 3特性

        1.单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

        2.没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题

        3.不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

  • 相关阅读:
    System.ServiceModel.CommunicationException: 接收HTTP 响应时错误发生
    "智囊"王沪宁先后辅佐三任总书记 _中国经济网
    xx
    我告诉你哦,最好吃的海南鸡饭不在海南…
    服务密码重置_中国移动通信
    移动服务密码怎么查_服务密码忘记了怎么办_百度经验
    http://www.sohu.com/a/162795109_465329
    首页--易配菜-中国餐饮行业最大的综合解决方案提供商
    浙江方圆工程咨询有限公司
    MySQL中间件方案盘点_搜狐科技_搜狐网
  • 原文地址:https://www.cnblogs.com/chengmr/p/13297638.html
Copyright © 2011-2022 走看看