redis 实现
redis事务的执行步骤如下
- 监视 (watch key)
- 开始 (multi)
- 入队 (set 等redis命令)
- 执行 (exec)
事务实现要点
客户端分为执行状态和事务状态,如果是执行状态,则该客户端的命令,redis立即执行;如果是事务状态,则添加到一个队列中,等待事务exec命令过来,全部执行。
每个redis客户端都有一个redisClient结构对象,那么该对象中保存了客户端的状态。
// 事务命令对象
typedef struct multiCmd{
// 参数
robj **argv;
// 参数数量
int argc;
// 命令指针
struct redisCommand *cmd;
}
typedef struct multiState{
// 事务命令队列
multiCmd *commands;
// 已入队命令计数
int count;
}
// 客户端数据对象
typedef struct redisClient{
//...
multiState mstate; /* MULTI / EXEC state */
//...
}
- multi 就是设置客户端为事务状态
void multiCommand(Client *c){
if (c->flag & CLIENT_MULTI){
addReplyError(c, ".....");
return;
}
c->flags |= CLIENT_MULTI;
addReply(c, SHARED, OK);
}
- 入队 QUEUE
if (c->flags & CLIENT_MULTI){
加入命令队列(该命令队列是一个数组类型)
}else{
立即执行
}
- 执行 exec
void exec(client *c){
if (c->flags & CLIENT_DIRTY_CAS | CLIENT_DIRTY_EXEC){
// 如果放弃执行事务或者是因为watch的key发生改变,则该事务不执行
discardTransaction(c);
return;
}
unwatchAllKeys(c); // 清理掉watch的所有key
reply = {}
for(命令队列){
result = call(执行一条命令)
addResultToReply(reply, result)
}
discardTransaction(c); // 取消客户端的事务状态
}