zoukankan      html  css  js  c++  java
  • 第十九章 事务

    Redis的事务是指将多个命令请求打包,一次性地,按顺序执行的机制。通过MULTI、EXEC、WATCH等命令实现事务功能。

    19.1 事务的实现

      19.1.1 事务的开始

      MULTI命令的执行代表了一个事务的开始,会将执行该命令的客户端由非事务状态切换成事务状态(在客户端状态的flags属性中打开REDIS_MULTI标识)

      19.1.2 命令入队

    • 非事务状态下,一个命令会被服务器立即执行。
    • 事务状态
      • EXEC、DISCARD、WATCH、MULTI命令会被立即执行
      • 其余命令放入一个事务队列,向客户端返回QUEUED回复

      19.1.3 事务队列

      每个Redis客户端由自己的事务状态,保存在mstate属性中

    typedef struct redisClient{
        //事务状态
        multiState mstate;
        //...
    
    } 

      事务状态包含了一个事务队列(一个multiCmd类型的数组),以及入队命令的计数器

    typedef struct multiState{
        //事务队列,FIFO顺序
        multiCmd *commands;
        //已入队命令计数器
        int count;
    }multiState;
    typedef struct multiCmd{
        //参数
        robj **argv;
        //参数数量
        int argc;
        //命令指针
        struct redisCommand *cmd;
    
    }multiCmd;

      19.1.4 执行事务

      当处于事务状态的客户端向服务器发送EXEC命令时,服务器会将客户端状态事务队列中的所有命令顺序执行,每执行完一个命令将结果暂存,全部执行完之后,移除客户端的事务状态标识,并清空客户端的事务状态,包括入队命令计数器和释放事务队列,最后将所有结果返回给客户端

    19.2 WATCH命令的实现

      WATCH命令是一个乐观锁,用于监测任意数量的数据库键,在EXEC执行时,检测被监视的键是否至少有一个已经被修改了,如果是的话,服务器将拒绝执行事务,并向客户端返回代表事务执行失败的空回复。

      19.2.1 使用WATCH命令监视数据库键

      每个Redis数据库保存了一个watched_keys字典,字典的键是被监视的数据库的键,字典的值是一个链表,保存了监视这个键的所有客户端  

    typedef struct redisDb{
        //正在被WATCH命令监视的键
        dict *watched_keys;
        //...
    }redisDb;

      客户端通过执行WATCH命令,将自身添加到watched_keys字典当中

      19.2.2 监视机制的触发

      所有对数据库进行键相关的操作命令,在执行完毕之后,都会检查watched_keys字典,查看相应的键是否有正在监视的客户端,有的话,会打开对应客户端的REDIS_DIRTY_CAS标识,表示该客户端的事务安全性被破坏

      19.2.3 判断事务是否安全

      当客户端发起EXEC命令时,服务器会检查当前客户端是否打开了REDIS_DIRTY_CAS标识,打开则拒绝执行事务

    19.3 事务的ACID性质

      A原子性,C一致性,I隔离性,D持久性

      19.3.1 原子性

      事务队列中的命令要么都执行,要么都不执行。这中间会存在某条命令执行出错的情况,Redis的事务不支持回滚,命令执行出错依然继续执行后续的命令

      19.3.2 一致性   

      事务执行前后,数据库状态都是一致的。一致是指,数据库中没有非法或者无效的错误数据。可能存在的错误如下

    1. 入队错误:命令格式错误或者命令的执行函数不存在,会拒绝执行整个事务
    2. 执行错误:执行出错会有相应的错误处理,不会修改数据库
    3. 服务器停机:如果有持久化操作,还原之后不会存在错误数据,如果没有,空白的数据库也不存在错误数据

      19.3.3 隔离性

      多个时间的执行不会相互干扰,因为Redis使用单线程的方式执行事务,执行事务期间不会中断,即Redis中的事务均是以串行的方式执行

      19.3.4 持久性

      只有在事务执行完成之后,这次事务中的命令全部被持久化,才具备持久性。只有AOF持久化模式,并且appendfsync选项为always时,事务具有持久性

    19.4 单线程处理请求的Redis为何需要事务

      单个服务器可以处理多个客户端的请求,中间的处理过程可能是交替执行的,某个客户端想要自己的命令被连续执行,则需要开启事务

      

    人生就像蒲公英,看似自由,其实身不由己。
  • 相关阅读:
    缓冲区溢出漏洞实验
    编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能
    预备作业01
    20155335俞昆的第2次随笔
    20155335俞昆
    团队博客
    小组项目第三周(20145101、20145102、20145124、20145203)
    小组项目第二周(20145101、20145102、20145124、20145203)
    小组项目第一周(20145101、20145102、20145124、20145203)
    项目总结
  • 原文地址:https://www.cnblogs.com/walker993/p/14477121.html
Copyright © 2011-2022 走看看