标签:star 隔离 有一个 code 服务器 错误处理 字典 flags cli
Redis通过MULTI、EXEC、WATCH、DISCARD等命令来实现事务功能。主要有以下三个阶段:
MULTI命令的执行,标识着一个事务的开始。MULTI命令会将客户端状态的flags
属性中打开REDIS_MULTI
标识来完成的。
当一个客户端切换到事务状态之后,服务器会根据这个客户端发送来的命令来执行不同的操作。如果客户端发送的命令为MULTI、EXEC、WATCH、DISCARD中的一个,立即执行这个命令,否则将命令放入一个事务队列里面,然后向客户端返回QUEUED
回复
typedef struct client {
// ......
// 事务状态(MULTI或者EXEC)
multiState mstate;
// ......
} client;
typedef struct multiState {
// 事务队列,FIFO
multiCmd *commands;
// 已入队命令计数
int count;
// ......
} multiState;
typedef struct multiCmd {
// 参数
robj **argv;
// 参数数量
int argc;
// 命令指针
struct redisCommand *cmd;
} multiCmd;
事务队列是按照FIFO的方式保存入队的命令
当一个处于事务状态的客户端向服务器发送EXEC命令时,服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令,最后将执行完的结果全部返回给客户端(每个命令对应一个返回)
WATCH命令是一个乐观锁,它可以在EXEC命令执行之前,监视任意数量的数据库键,并在执行EXEC命令时,检查被监视的键是否至少有一个已经被修改,如果有,服务器拒绝执行事务,向客户端返回代表事务执行失败的空回复
watched_keys
字典,服务器可以清除地知道哪些数据库键正在被监视,以及哪些客户端正在监视这些数据库键typedef struct redisDb {
// ......
// 正在被WATCH命令监视的键
dict *watched_keys;
// ......
} redisDb;
touchWatchKey
函数对watched_keys
字典进行检查,如果有客户端监视的key被修改过,那么touchWatchKey
函数会将监视被修改的客户端的REDIS_DIRTY_CAS
标识打开,表示事务已经被破坏REDIS_DIRTY_CAS
标识被打开了,说明客户端提交的事务已经不再安全,所以服务器会拒绝执行客户端提交的事务原子性:对于Redis的事务功能来说,事务队列中的命令要么就全部执行,要么就一个都不执行,但是Redis的事务是不支持回滚操作的
一致性:Redis通过谨慎的错误检测和简单的设计保证事务的一致性。Redis事务可能出错的地方以及解决方案:
隔离性:Redis使用单线程的方式执行事务,并且服务器保证在执行事务期间不会对事务进行中断,因此,Redis的事务总是串行的方式运行,并且事务总是具有隔离性的
耐久性:当服务器运行在AOF持久化模式下,并且appendfsync
选项的值是always
时,事务是具有耐久性的,其他情况不具有耐久性
标签:star 隔离 有一个 code 服务器 错误处理 字典 flags cli
原文地址:https://www.cnblogs.com/pinxiong/p/13288112.html