• Redis 源码学习之 Redis 事务Nosql


    Redis事务提供了一种将多个命令请求打包,然后一次性、按照顺序地执行多个命令的机制,并且在事务执行的期间,服务器不会中断事务而去执行其他不在事务中的命令请求,它会把事务中所有的命令都执行完毕才会去执行其他的命令。

    How

    Redis中提供了multi、discard、exec、watch、unwatch这几个命令来实现事务的功能。

    Redis的事务始于multi命令,之后跟着要在事务中执行的命令,终于exec命令或者discard命令。加入事务中的所有命令会原子的执行,中间不会穿插执行其他没有加入事务的命令。

    multi、exec和discard

    multi命令告诉Redis客户端要开始一个事物,然后Redis会返回一个OK,接下来所有的命令Redis都不会立即执行,只会返回QUEUED结果,直到遇到了exec命令才会去执行之前的所有的命令,或者遇到了discard命令,会抛弃执行之前加入事务的命令。

    127.0.0.1:6379> get name

    (nil)

    127.0.0.1:6379> get gender

    (nil)

    127.0.0.1:6379> multi

    OK

    127.0.0.1:6379> set name Slogen

    QUEUED

    127.0.0.1:6379> set gender male

    QUEUED

    127.0.0.1:6379> exec

    1) OK

    2) OK

    127.0.0.1:6379> mget name gender

    1) "Slogen"

    2) "male"

    watch

    watch命令是Redis提供的一个乐观锁,可以在exec执行之前,监视任意数量的数据库key,并在exec命令执行的时候,检测被监视的key是否至少有一个已经被修改,如果是的话,服务器将拒绝执行事务,并向客户端返回代表事务执行失败的空回复。

    首先在client1执行下列命令:

    127.0.0.1:6379> get name

    (nil)

    127.0.0.1:6379> watch name

    OK

    127.0.0.1:6379> multi

    OK

    127.0.0.1:6379> set name slogen

    QUEUED

    127.0.0.1:6379> set gender male

    QUEUED

    127.0.0.1:6379> get name

    QUEUED

    这个时候client还没有执行exec命令,接下来在client2下执行下面命令修改name:

    127.0.0.1:6379> set name rio

    OK

    127.0.0.1:6379> get name

    "rio"

    接下来在client1下执行exec命令:

    127.0.0.1:6379> exec

    (nil)

    127.0.0.1:6379> get name

    "rio"

    从执行结果可以看到,在client1中执行exec命令的时候,Redis会检测到name字段已经被其他客户端修改了,所以拒绝执行事务中所有的命令,直接返回nil表示执行失败。这个时候获取到的name的值还是在client2中设置的rio。

    Why

    multi

    Redis的事务始于multi命令,那么就从multi命令的源代码开始分析。

    当Redis接收到客户端发送过来的命令之后会执行multiCommand()这个方法,这个方法在multi.c文件中。

    void multiCommand(client *c) {

    // 1. 如果检测到flags里面已经包含了CLIENT_MULTI

    // 表示对应client已经处于事务的上下文中,返回错误

    if (c->flags & CLIENT_MULTI) {

    addReplyError(c,"MULTI calls can not be nested");

    return;

    }

    // 2. 开启flags的CLIENT_MULTI标识

    c->flags |= CLIENT_MULTI;

    // 3. 返回ok,告诉客户端已经成功开启事务

    addReply(c,shared.ok);

    }

    从源代码中可以看到,multiCommand()主要完成下面三件事:

    检测发送multi命令的client是否已经处于事务中,如果是则直接返回错误。从这里可以看到,Redis不支持事务嵌套执行。

    给对应client的flags标志位中增加MULTI_CLIENT标志,表示已经进入事务中。

    返回OK告诉客户端已经成功开启事务。

  • 相关阅读:
    Asp.Net MVC中Controller与View之间传递的Model
    Asp.Net MVC中DropDownListFor的用法
    在Window的IIS中创建FTP的Site并用C#进行文件的上传下载
    在Salesforce中创建Web Service供外部系统调用
    在Salesforce中处理Xml的生成与解析
    JS 正则表达式详解
    【LeetCode】211. Add and Search Word
    【LeetCode】210. Course Schedule II
    【LeetCode】209. Minimum Size Subarray Sum
    【LeetCode】208. Implement Trie (Prefix Tree)
  • 原文地址:https://www.cnblogs.com/2881064178dinfeng/p/6994391.html
Copyright © 2020-2023  润新知