zoukankan      html  css  js  c++  java
  • Redis事务

    1. Redis事务是什么

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

    2. Redis事务的实现

    Redis事务的实现需要用到 MULTI  EXEC 两个命令,事务开始的时候先向Redis服务器发送 MULTI 命令,然后依次发送需要在本次事务中处理的命令,最后再发送 EXEC 命令表示事务命令结束。

    2.1 正常执行

    通过MULTI  EXEC 两个命令演示正常的事务执行生效过程。

    从输出中可以看到,当输入 MULTI 命令后,服务器返回OK表示事务开始成功,然后依次输入需要在本次事务中执行的所有命令,每次输入一个命令服务器并不会马上执行,而是返回”QUEUED”,这表示命令已经被服务器接受并且暂时保存起来,最后输入EXEC命令后,本次事务中的所有命令才会被依次执行,可以看到最后服务器一次性返回了三个OK,这里返回的结果与发送的命令是按顺序一一对应的,这说明这次事务中的命令全都执行成功了。

    如果客户端在发送EXEC命令之前断线了,则服务器会清空事务队列,事务中的所有命令都不会被执行。而一旦客户端发送了EXEC命令之后,事务中的所有命令都会被执行,即使此后客户端断线也没关系,因为服务器已经保存了事务中的所有命令。

    2.2 全体连坐

    语法错误会使得事务中的命令全部不执行。

    语法错误表示命令不存在或者参数错误,这种情况需要区分Redis的版本,2.6.5之后的版本会忽略这个事务中的所有命令,都不执行。Redis 2.6.5之前的版本会忽略错误的命令,执行其他正确的命令。下面是我使用redis2.4.5测试的截图。

    2.3 冤头债主

    运行错误会使得事务跳过有错的语句,仅执行无报错的任务。

     

    运行错误表示命令在执行过程中出现错误,比如给非数字值增一、用GET命令获取一个散列表类型的键值等。这种错误在命令执行之前Redis是无法发现的,所以在事务里这样的命令会被Redis接受并执行。如果事务里有一条命令执行错误,其他命令依旧会执行(包括出错之后的命令)。

    2.4 WATCH 监控

    WATCH命令是一个乐观锁,它可以在EXEC命令执行之前,监视任意数量的数据库键,并在EXEC执行时,检查被监视的键是否至少有一个已经被修改过了,如果是的话,服务器将拒绝执行事务,并向客户端返回执行失败的nil回复。

    EXEC命令执行完之后被监控的键会自动被UNWATCH,另外UNWATCH命令也可以在WATCH命令执行之后、MULTI命令执行之前取消对某个键的监控。

    2.5 放弃事务

    放弃事务使用 DISCARD 命令,DISCARD命令可以在 MULTI 命令执行之后,EXEC 命令执行之前取消 WATCH 命令并清空事务队列,然后从事务状态中退出。

     

    3. 为什么Redis不支持回滚

    如果你有使用关系式数据库的经验, 那么 “Redis 在事务失败时不进行回滚,而是继续执行余下的命令”这种做法可能会让你觉得有点奇怪。

    以下是这种做法的优点:

    • Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
    • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

    有种观点认为 Redis 处理事务的做法会产生 bug , 然而需要注意的是, 在通常情况下, 回滚并不能解决编程错误带来的问题。 举个例子, 如果你本来想通过 INCR 命令将键的值加上 1 , 却不小心加上了 2 , 又或者对错误类型的键执行了 INCR , 回滚是没有办法处理这些情况的。

    鉴于没有任何机制能避免程序员自己造成的错误, 并且这类错误通常不会在生产环境中出现, 所以 Redis 选择了更简单、更快速的无回滚方式来处理事务

    4. Redis事务的总结

    Redis事务实现分为三个阶段:

    • 开启:以MULTI开始一个事务。
    • 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面。
    • 执行:由EXEC命令触发事务。

    Redis事务的三个特性:

    • 单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
    • 没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”的问题。
    • 不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚。

      

  • 相关阅读:
    HANDLER进行堆叠注入
    CDUT第一届信安大挑战Re-wp
    Nu1LBook第一章wp
    Linux和VMWare
    [MRCTF]Xor
    IDA 调整栈帧 (411A04:positive sp value has been found)
    [BUU] 简单注册器
    2020年“安洵杯”四川省大学生信息安全技术大赛 部分WRITEUP
    关于我的pip不听话,总是说【Fatal error in launcher: Unable to create process using '"'】这件事
    C语言的PELode编写记录
  • 原文地址:https://www.cnblogs.com/zjfjava/p/10994026.html
Copyright © 2011-2022 走看看