【笔记】《Redis设计与实现》chapter19 事务

chapter19 事务

Redis通过MULTI、EXEC、WATCH等命令来实现事务功能

19.1 事务的实现

事务开始

redis> MULTI
ok

通过切换客户端状态的flag属性的REDIS_MULTI标识来完成

命令入队

事务队列

struct redisServer{
      // 事务状态
    multiState mstate;      /* MULTI/EXEC state */  
};

/*
 * 事务命令
 */
typedef struct multiCmd {

    // 参数
    robj **argv;

    // 参数数量
    int argc;

    // 命令指针
    struct redisCommand *cmd;

} multiCmd;

/*
 * 事务状态
 */
typedef struct multiState {

    // 事务队列,FIFO 顺序
    multiCmd *commands;     /* Array of MULTI commands */

    // 已入队命令计数
    int count;              /* Total number of MULTI commands */
    int minreplicas;        /* MINREPLICAS for synchronous replication */
    time_t minreplicas_timeout; /* MINREPLICAS timeout as unixtime. */
} multiState;

执行事务

image-20201016114628683

19.2 WATCH 命令的实现

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

使用WATCH命令监视数据库键

struct redisDb{
        // 键正在被 WATCH 命令监视的键,值为客户端链表
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */
};

监视机制的触发

所有对数据库进行修改的命令在执行前都会调用multi.c/touchWatchKey函数对wached_keys字典进行检查,查看是否有客户端正在监视刚刚被命令修改过的数据库键,如果有的话,那么函数会将监视修改键的客户端REDIS_DIRTY_CAS标识打开,标识该客户端的事务安全性已经被破坏。

touchWatchKey函数的定义可以用以下伪代码来描述:

image-20201016230808406

判断事务是否安全

当客户端接收到一个客户端发来的EXEC命令时,服务器会根据这个客户端是否打开了REDIS_DIRTY_CAS标识来决定是否执行事务

一个完整的WATCH事务执行过程

19.3 事务的 ACID 性质

在REDIS中,事务总具有原子性(Atomicity)、一致性(Consistency)和隔离性(Isolation),当Redis运行在某种特定的持久化模式下时,事务也具有耐久性(Durability)

原子性

一致性

posted @ 2021-04-20 11:43  汉森伯逸  阅读(43)  评论(0编辑  收藏  举报