redis中事务的取消

redis的事务不能实现回滚,但是可以在正在执行的事务中通过discard 命令来取消事务的执行。
struct redisCommand redisCommandTable[] = {

    {"discard",discardCommand,1,"rs",0,NULL,0,0,0,0,0},
}
void discardCommand(redisClient *c) {

    // 可见这个命令是要在事务中进行没负责直接返回error
    if (!(c->flags & REDIS_MULTI)) {
        addReplyError(c,"DISCARD without MULTI");
        return;
    }
	// 调用这个函数清空redisClint.mstate.command这个数组
    discardTransaction(c);

    addReply(c,shared.ok);
}
void discardTransaction(redisClient *c) {

    // 删除事务中已经入队的命令
    freeClientMultiState(c);
	// 重新初始化事务的队列
    initClientMultiState(c);

    // 取消在执行事务是设置的flags
    c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS|REDIS_DIRTY_EXEC);;

    // 取消对所有键的监视
    unwatchAllKeys(c);
}
我们首选看freeClientMultiState 是如此删除事务中已经保存的命令
void freeClientMultiState(redisClient *c) {
    int j;

    // 遍历事务中已经保存的命令,命令的总数用mstate.count表示
    for (j = 0; j < c->mstate.count; j++) {
        int i;
        multiCmd *mc = c->mstate.commands+j;

        // 释放所有命令参数
        for (i = 0; i < mc->argc; i++)
            decrRefCount(mc->argv[i]);

        // 释放参数数组本身
        zfree(mc->argv);
    }

    // 释放保存事务命令的数组占用的内存
    zfree(c->mstate.commands);
}
其次initClientMultiState 主要用于重新初始化命令保存对了和命令总数
void initClientMultiState(redisClient *c) {

    // 保存命令的数组置
    c->mstate.commands = NULL;

    // 命令计数归零
    c->mstate.count = 0;
}
最后看看如何取消所有的key的监视
void unwatchAllKeys(redisClient *c) {
    listIter li;
    listNode *ln;

    //如果redisClient中的watched_keys 为零,说明没有key 被监视,则就不用取消了,直接返回
    if (listLength(c->watched_keys) == 0) return;

    // 
    listRewind(c->watched_keys,&li);
    while((ln = listNext(&li))) {
        list *clients;
        watchedKey *wk;

        /* Lookup the watched key -> clients list and remove the client
         * from the list */
        // 找到要删除的key
        wk = listNodeValue(ln);
        // 根据key取出list *clients
        clients = dictFetchValue(wk->db->watched_keys, wk->key);
		// client 不能为null
        redisAssertWithInfo(c,NULL,clients != NULL);
        // 删除链表中的客户端节点
        listDelNode(clients,listSearchKey(clients,c));

        /* Kill the entry at all if this was the only client */
        // 如果client已经为null,则删除client 对应的key
        if (listLength(clients) == 0)
            dictDelete(wk->db->watched_keys, wk->key);

        /* Remove this watched key from the client->watched list */
        // 从
        listDelNode(c->watched_keys,ln);

        decrRefCount(wk->key);
        zfree(wk);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值