Redis-Redi事务注意事项

  当客户端处于非事务状态下时, 所有发送给服务器端的命令都会立即被服务器执行。但是, 当客户端进入事务状态之后, 服务器在收到来自客户端的命令时, 不会立即执行命令, 而是将这些命令全部放进一个事务队列里, 然后返回 QUEUED , 表示命令已入队。

  但其实并不是所有的命令都会被放进事务队列, 其中的例外就是 EXEC 、 DISCARD 、 MULTI 和 WATCH 这四个命令 —— 当这四个命令从客户端发送到服务器时, 它们会像客户端处于非事务状态一样, 直接被服务器执行。

  事务的执行可以用如下伪代码描述:

def execute_transaction():

    # 创建空白的回复队列
    reply_queue = []

    # 取出事务队列里的所有命令、参数和参数数量
    for cmd, argv, argc in client.transaction_queue:

        # 执行命令,并取得命令的返回值
        reply = execute_redis_command(cmd, argv, argc)

        # 将返回值追加到回复队列末尾
        reply_queue.append(reply)

    # 清除客户端的事务状态
    clear_transaction_state(client)

    # 清空事务队列
    clear_transaction_queue(client)

    # 将事务的执行结果返回给客户端
    send_reply_to_client(client, reply_queue)

  不过事务中的命令和普通命令在执行上还是有一点区别的,其中最重要的两点是:

    非事务状态下的命令以单个命令为单位执行,前一个命令和后一个命令的客户端不一定是同一个。而事务状态则是以一个事务为单位,执行 exec 后(放入队列不算)会执行事务队列中的所有命令,除非当前事务执行完毕,否则服务器不会中断事务,也不会执行其他客户端的其他命令。执行 exec 后才进入真正执行事务状态(不被中断)

    在非事务状态下,执行命令所得的结果会立即被返回给客户端,而事务则是将所有命令的结果集合到回复队列,再作为 EXEC 命令的结果返回给客户端。

  DISCARD 命令用于取消一个事务, 它清空客户端的整个事务队列, 然后将客户端从事务状态调整回非事务状态, 最后返回字符串 OK 给客户端, 说明事务已被取消。

  Redis 的事务是不可嵌套的, 当客户端已经处于事务状态, 而客户端又再向服务器发送 MULTI 时, 服务器只是简单地向客户端发送一个错误, 然后继续等待其他命令的入队。 MULTI 命令的发送不会造成整个事务失败, 也不会修改事务队列中已有的数据。

  WATCH 只能在客户端进入事务状态之前执行, 在事务状态下发送 WATCH 命令会引发一个错误, 但它不会造成整个事务失败, 也不会修改事务队列中已有的数据(和前面处理 MULTI 的情况一样)。该命令用于在事务开始之前监视任意数量的键,当调用 EXEC 命令执行事务时, 如果任意一个被监视的键已经被其他客户端修改了, 那么整个事务不再执行, 直接返回失败。 即下图中客户端 A 将执行失败。

  在时间 T4 ,客户端 B 修改了 name 键的值, 当客户端 A 在 T5 执行 EXEC 时,Redis 会发现 name 这个被监视的键已经被修改, 因此客户端 A 的事务不会被执行,而是直接返回失败。

  WATCH 实现:在每个代表数据库的 redis.h/redisDb 结构类型中, 都保存了一个 watched_keys 字典, 字典的键是这个数据库被监视的键, 而字典的值则是一个链表, 链表中保存了所有监视这个键的客户端。

  

  举个例子, 如果当前客户端为 client10086 , 那么当客户端执行 WATCH key1 key2 时, 前面展示的 watched_keys 将被修改成这个样子:

  在任何对数据库键空间(key space)进行修改的命令成功执行之后 (比如 FLUSHDB 、 SET 、 DEL 、 LPUSH 、 SADD 、 ZREM ,诸如此类), multi.c/touchWatchedKey 函数都会被调用 —— 它检查数据库的 watched_keys 字典, 看是否有客户端在监视已经被命令修改的键, 如果有的话, 程序将所有监视这个/这些被修改键的客户端的 REDIS_DIRTY_CAS 选项打开。

  当客户端发送 EXEC 命令、触发事务执行时, 服务器会对客户端的状态进行检查:

    如果客户端的 REDIS_DIRTY_CAS 选项已经被打开,那么说明被客户端监视的键至少有一个已经被修改了,事务的安全性已经被破坏。服务器会放弃执行这个事务,直接向客户端返回空回复,表示事务执行失败。
    如果 REDIS_DIRTY_CAS 选项没有被打开,那么说明所有监视键都安全,服务器正式执行事务。

#参考实现代码def check_safety_before_execute_trasaction():

    if client.state & REDIS_DIRTY_CAS:
        # 安全性已破坏,清除事务状态
        clear_transaction_state(client)
        # 清空事务队列
        clear_transaction_queue(client)
        # 返回空回复给客户端
        send_empty_reply(client)
    else:
        # 安全性完好,执行事务
        execute_transaction()

  Redis 事务的 ACID 性质

时间: 2024-12-17 10:51:09

Redis-Redi事务注意事项的相关文章

Redis的事务功能详解

Redis的事务功能详解 MULTI.EXEC.DISCARD和WATCH命令是Redis事务功能的基础.Redis事务允许在一次单独的步骤中执行一组命令,并且可以保证如下两个重要事项: >Redis会将一个事务中的所有命令序列化,然后按顺序执行.Redis不可能在一个Redis事务的执行过程中插入执行另一个客户端发出的请求.这样便能保证Redis将这些命令作为一个单独的隔离操作执行. > 在一个Redis事务中,Redis要么执行其中的所有命令,要么什么都不执行.因此,Redis事务能够保证

Redis的事务机制

1.redis的事务是什么 可以一次执行多个命令,本质是一组命令的集合,一个事务中的所有命令都会被序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞(排队时后来者插到先到者前面的行为.) 也就是说,在队列中,一次性.顺序性.排他性的执行一系列命令的行为. 看看官方的介绍: 注: redis 的事务是能够使用 MULTI 命令的行为,这个命令通常会响应为 OK,在这种情况下,使用者可以进行多个命令的操作,redis会安排它们入队列而不是执行这些命令,这些所有命令在键入 EXEC 时才会被调用

Redis的事务

Redis对事务的支持是部分支持,不想oracle,要么都成功要么都失败,Redis可以部分成功部分失败 1 是什么: 可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不许加塞 2 能干嘛: 一个队列中,一次性.顺序性.排他性的执行一系列命令 3 怎么玩 Redis 事务命令 下标列出了redis事务的相关命令 1. DISCARD 取消事务,放弃执行事务块内的所有命令. 2. EXEC 执行所有事务块内的命令 3. MULTI

WINDOWS 下, Redis 单机事务测试

WIN 10: i5 4440, 8GB 测试REDIS的事务速度 REDIS的WATCH机制实现事务是一个乐观锁形式(应该是SPIN LOCK的一种).适用于并发度不是很高的场景,可以节约CPU资源(轻量级锁).但是当竞争激烈的情况下,失败概率会大大提升,大量失败后的重试会耗费CPU资源. 测试的逻辑 1)读取计数器 2)JAVA端自增 3)设置回REDIS 此处不可用REDIS自带的incr函数,REDIS服务器端为单线程执行,所以服务器端只执行一个incr指令的情况下,其实可以看作原子操作

node.js redis对事务的控制

redis对事务的支持还是比较差的,就是把所有的执行命令方到队列中一个一个执行 multi开启一个事务,exec执行事务集合中的命令 代码: var redisClient; redisClient.multi([        ["set", "ttt_1", "1111111"],        ["incr", "ttt_2"],        ["incr", "ttt

[转]@Transactional spring 配置事务 注意事项

@Transactional spring 配置事务 注意事项 [@[email protected]] @Transactional spring 配置事务 注意事项 1. 在需要事务管理的地方加@Transactional 注解.@Transactional 注解可以被应用于接口定义和接口方法.类定义和类的 public 方法上. 2. @Transactional 注解只能应用到 public 可见度的方法上. 如果你在 protected.private 或者 package-visib

@Transactional spring 配置事务 注意事项

http://epine.itpub.net/post/8159/526281 @Transactional spring 配置事务 注意事项 1. 在需要事务管理的地方加@Transactional 注解.@Transactional 注解可以被应用于接口定义和接口方法.类定义和类的 public 方法上. 2. @Transactional 注解只能应用到 public 可见度的方法上. 如果你在 protected.private 或者 package-visible 的方法上使用 @Tr

第三课作业——set类型、sorted set类型的增删改查,redis的事务

第三课时作业 静哥 by 2016.2.23~2016.3.6   [作业描述] 1.总结什么是set以及什么是sorted set,并完成对set以及sorted set的增删改查(查需要至少4种方式,比如列表,单个节点等) 2.总结redis的事务特征,并且实际操作事务的提交  丢弃以及乐观锁 [作业一:总结什么是set以及什么是sorted set,并完成对set以及sorted set的增删改查] (1) set是字符串的无序集合,集合内的成员可以是重复: sorted set是有序集合

redis之(九)redis的事务机制

[一]什么是redis的事务 --->redis的事务是一组命令的集合. --->redis的事务是保证一组命令,要么都执行,要么都不执行.但不支持一组命令中,其中一个或多个执行失败,不支持数据回滚.数据的一致性,由程序员控制. --->redis的事务还能保证一个事务内的命令依次执行,而不被其他命令插入.试想,客户端 A发送几条命令到redis服务器,客户端B也送了一条命令也到redis服务器上.如果不使用事务,则客户端 B的那条命令就有可能在客户端A的那几条命令中间执行. [二]re