【笔记】《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;
执行事务
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函数的定义可以用以下伪代码来描述:
判断事务是否安全
当客户端接收到一个客户端发来的EXEC命令时,服务器会根据这个客户端是否打开了REDIS_DIRTY_CAS标识来决定是否执行事务
一个完整的WATCH事务执行过程
19.3 事务的 ACID 性质
在REDIS中,事务总具有原子性(Atomicity)、一致性(Consistency)和隔离性(Isolation),当Redis运行在某种特定的持久化模式下时,事务也具有耐久性(Durability)