Redis源码剖析和注释(二十八)--- Redis 事务实现和乐观锁

Redis 事务实现和乐观锁

1. 事务的介绍

Redis事务(transaction)提供了以下五个命令,用于用户操作事务功能,其分别是:

命令 功能
MULTI 标记一个事务块的开始
DISCARD 放弃执行事务
EXEC 执行事务中的所有命令
WATCH 监视一个或多个key,如果至少有一个key在EXEC之前被修改,则放弃执行事务
UNWATCH 取消WATCH命令对所有键的监视

- 事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务的执行期间,服务器不会打断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕,然后才去执行其他客户端的命令请求。
- Redis中的事务(transaction)是一组命令的集合。事务同命令一样都是Redis中的最小执行单位,一个事务中的命令要么都执行,要么都不执行。

事务命令的使用方法请看:Redis 事务命令
Redis 事务源码详细注释

2. 事务的实现

执行事务的过程分为以下的几个阶段:

  • 开始事务
  • 命令入队
  • 执行事务

2.1 开始事务

在客户端执行一个MULTI命令,标记一个事务块的开始。该命令会被封装成Redis协议的格式发送给服务器,服务器接收到该命令会调用multiCommand()函数来执行。函数源码如下:

Redis 命令接收/回复过程的源码剖析

void multiCommand(client *c) {
    // 客户端已经处于事务状态,回复错误后返回
    if (c->flags & CLIENT_MULTI) {
        addReplyError(c,"MULTI calls can not be nested");
        return;
    }
    // 打开客户的的事务状态标识
    c->flags |= CLIENT_MULTI;
    // 回复OK
    addReply(c,shared.ok);
}

该函数首先先会判断当前客户端是否处于事务状态(CLIENT_MULTI),如果没有处于事务状态,那么会打开客户端的事务状态标识,并且回复客户端一个OK

执行完MULTI命令,表示着一个事务的开始。

2.2 命令入队

由于事务的命令是一次性、按顺序的执行,因此,需要将客户端中的所有事务命令事前保存起来。Redis 事务源码详细注释

在每个描述客户端状态的结构struct client中,保存着有关事务状态的成员变量,他的定义如下:

typedef struct client {
    // 事物状态
    multiState mstate;
} client;

multiState是一个结构体,定义如下:

typedef struct multiState {
    // 事务命令队列数组
    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;

重点关注前两个属性。

  • commands成员是一个指针,保存的是一个成员类型为multiCmd的数组首地址,每一个成员保存的都是事务命令。
  • count成员保存的是以commands为地址的数组的成员个数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值