redis源码解读4

这篇我们插一段关于redis中事务的讨论。

相关的命令:
    MULTI:事务的开始
    EXEC:事务的执行
    WATCH:监视数据库键
    DISCARD:停止事务
源码在multi.c中

void multiCommand(redisClient *c) {
    if (c->flags & REDIS_MULTI) {
        addReplyError(c,"MULTI calls can not be nested");
        return;
    }
    //打开事务标识
    c->flags |= REDIS_MULTI;
    addReply(c,shared.ok);
}

void execCommand(redisClient *c) {
    int j;
    robj **orig_argv;
    int orig_argc;
    struct redisCommand *orig_cmd;
    int must_propagate = 0; /* Need to propagate MULTI/EXEC to AOF / slaves? */

    if (!(c->flags & REDIS_MULTI)) {
        addReplyError(c,"EXEC without MULTI");
        return;
    }

    if (c->flags & (REDIS_DIRTY_CAS|REDIS_DIRTY_EXEC)) {
        addReply(c, c->flags & REDIS_DIRTY_EXEC ? shared.execaborterr :
                                                  shared.nullmultibulk);
        discardTransaction(c);
        goto handle_monitor;
    }
    unwatchAllKeys(c); /* Unwatch ASAP otherwise we'll waste CPU cycles */
    orig_argv = c->argv;
    orig_argc = c->argc;
    orig_cmd = c->cmd;
    addReplyMultiBulkLen(c,c->mstate.count);
    for (j = 0; j < c->mstate.count; j++) {
        c->argc = c->mstate.commands[j].argc;
        c->argv = c->mstate.commands[j].argv;
        c->cmd = c->mstate.commands[j].cmd;

        if (!must_propagate && !(c->cmd->flags & REDIS_CMD_READONLY)) {
            execCommandPropagateMulti(c);
            must_propagate = 1;
        }
        call(c,REDIS_CALL_FULL);
        c->mstate.commands[j].argc = c->argc;
        c->mstate.commands[j].argv = c->argv;
        c->mstate.commands[j].cmd = c->cmd;
    }
    c->argv = orig_argv;
    c->argc = orig_argc;
    c->cmd = orig_cmd;
    discardTransaction(c);
    if (must_propagate) server.dirty++;

handle_monitor:
    if (listLength(server.monitors) && !server.loading)
        replicationFeedMonitors(c,server.monitors,c->db->id,c->argv,c->argc);
}

接下里我们用图来介绍一下执行流程:
复制代码

下面再讨论一下redis中出错的处理机制。

命令错误:整个事务无法执行
运行时错误:需要人工参与
复制代码

注:redis不支持回滚

redis中的乐观锁:watch

接下里再看看redis事务的ACID性质

原子性:见上面redis的出错处理机制
一致性:
    服务器停机
        无持久化的内存模式,OK
        RDB模式,OK
        AOF模式,OK
隔离性
耐久性:AOF模式下appendfsync值为always时,OK

一致性和耐久性和redis的持久化密切相关,之后涉及到再进行谈论。
说完事务,对redis的pipeline也在此处进行了解,对比一下:

由上面的请求也可以看出了两者最明显的区别是客户端发送请求的方式不一样,具体相关区别如下:

pipeline选择客户端缓冲,multi选择服务端缓冲;
请求次数的不一致,multi需要每个命令都发送一次给服务端,pipeline最后一次性发送给服务端,请求次数相对于multi减少
multi/exec可以保证原子性,而pipeline不保证原子性
pipeline需要客户端自己开发配合,而且命令数不能太多,multi是redis服务端支持的,不需要client做任何事情复制代码

转载于:https://juejin.im/post/5c877181f265da2dc675f521

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值