Redis source code analysis 21-transaction

Source: Internet
Author: User
Redis transactions are simple and do not have all the acid features of transactions. One of the main reasons is that commands in redis transactions are not executed immediately and will be queued until the exec command is released to execute all the commands. Another major reason is that it does not support rollback, the commands in the transaction can be partially successful, partially failed, and not executed in the transaction context when the command fails.

Redis transactions are simple and do not have all the acid features of transactions. One of the main reasons is that commands in redis transactions are not executed immediately and will be queued until the exec command is released to execute all the commands. Another major reason is that it does not support rollback, the commands in the transaction can be partially successful, partially failed, and not executed in the transaction context when the command fails.

Redis transactions are simple and do not have all the acid features of transactions. One of the main reasons is that commands in redis transactions are not executed immediately and will be queued until the exec command is released to execute all the commands. Another major reason is that it does not support rollback, the commands in the transaction can be partially succeeded or partially failed. The command failure is similar to the information returned when the transaction context is not executed. I don't know if it will provide better support in the future.

Let's take a look at the implementation of redis transactions.

The main transaction-related structure in redis is as follows. The multiState of each redisClient saves the command to be executed in the transaction context.

/* Client MULTI/EXEC state */typedef struct multiCmd {    robj **argv;    int argc;    struct redisCommand *cmd;} multiCmd;typedef struct multiState {    multiCmd *commands;     /* Array of MULTI commands */    int count;              /* Total number of MULTI commands */} multiState;typedef struct redisClient {   ---    multiState mstate;      /* MULTI/EXEC state */    ---} redisClient;

The client publishes the multi command to enter the transaction context. The client in the transaction context sets the REDIS_MULTI flag, and the multi command returns immediately.

static void multiCommand(redisClient *c) {    c->flags |= REDIS_MULTI;    addReply(c,shared.ok);}

The client in the transaction context queues the commands released before the exec command to the mstate, does not immediately execute the corresponding command, and immediately returns shared. queued (if the previous parameter check is incorrect, an error message will be returned, and the message will not be queued to the mstate ), this is reflected in the processCommand function (for more information about processCommand, see the previous chapter on command processing ). QueueMultiCommand simply expands the mstate array and adds the current command to it.

static int processCommand(redisClient *c) {    ---   /* Exec the command */    if (c->flags & REDIS_MULTI && cmd->proc != execCommand && cmd->proc != discardCommand) {        queueMultiCommand(c,cmd);        addReply(c,shared.queued);    } else {        if (server.vm_enabled && server.vm_max_threads > 0 &&            blockClientOnSwappedKeys(c,cmd)) return 1;        call(c,cmd);    }    ---}

When the client releases the exec command, redis will call execCommand to execute the command set in the transaction context. Note: before that, redis will use execBlockClientOnSwappedKeys to load the key required for its command set in advance (this function is used to call waitForMultipleSwappedKeys as described earlier to load the key ). Because this is set in the Command table cmdTable as follows:

{"exec",execCommand,1,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,execBlockClientOnSwappedKeys,0,0,0},

ExecCommand checks whether it is in the transaction context, and then uses execCommandReplicateMulti to send/Write multi command words to slave/monitor/aof (provided that these functions are used), because the multi command itself is not queued, execCommand writes the exec command after execution, and must pair the exec and multi commands. After that, each command is executed by calling call. We can see that if the command fails to be executed, the call command itself can only return error information, but it does not check whether the command is successfully executed, finally, the command word in the mstate is cleared and the REDIS_MULTI state is canceled.

static void execCommand(redisClient *c) {    int j;    robj **orig_argv;    int orig_argc;    if (!(c->flags & REDIS_MULTI)) {        addReplySds(c,sdsnew("-ERR EXEC without MULTI\r\n"));        return;    }    /* Replicate a MULTI request now that we are sure the block is executed.     * This way we'll deliver the MULTI/..../EXEC block as a whole and     * both the AOF and the replication link will have the same consistency     * and atomicity guarantees. */    execCommandReplicateMulti(c);    /* Exec all the queued commands */    orig_argv = c->argv;    orig_argc = c->argc;    addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",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;        call(c,c->mstate.commands[j].cmd);    }    c->argv = orig_argv;    c->argc = orig_argc;    freeClientMultiState(c);    initClientMultiState(c);    c->flags &= (~REDIS_MULTI);    /* Make sure the EXEC command is always replicated / AOF, since we     * always send the MULTI command (we can't know beforehand if the     * next operations will contain at least a modification to the DB). */    server.dirty++;}

At last, if redis suddenly goes down during the execution of the transaction context, that is, the last exec command is not written, the slave/monitor/aof status will be incorrect. Redis will check this situation after restarting, which is completed in loadAppendOnlyFile. Of course, the premise of this check is that aof is used for persistence before and after the removal and restart. Redis will exit the program after detecting this situation. You can use the redis-check-aof tool to fix the vulnerability.

Original article address: redis source code analysis 21-transaction, thanks to the original author for sharing.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.