Fork me on GitHub

Redis事务

是什么

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

Redis事务的三个阶段

  • 开始事务
  • 命令入队
  • 执行事务

Redis 事务相关的命令及用法

MULTI 、 EXEC 、 DISCARD 和 WATCH 

MULTI命令用于开启一个事务,它总是返回 OK 。 MULTI 执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中, 当 EXEC命令被调用时, 所有队列中的命令才会被执行。

DISCARD通过调用 DISCARD , 客户端可以清空事务队列, 并放弃执行事务。

WATCH命令可以为 Redis 事务提供 check-and-set (CAS)行为,相当于加乐观锁。被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。 如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消, EXEC 返回nil-reply来表示事务已经失败。

EXEC命令负责触发并执行事务中的所有命令:

  • 如果客户端在使用 MULTI开启了一个事务之后,却因为断线而没有成功执行EXEC ,那么事务中的所有命令都不会被执行。
  • 另一方面,如果客户端成功在开启事务之后执行 EXEC,那么事务中的所有命令都会被执行。

事务中的错误

  • 若在事务队列中存在命令性错误,则执行EXEC命令时,所有命令都不会执行

  • 若在事务队列中存在语法性错误,则执行EXEC命令时,其他正确命令会被执行,错误命令抛出异常。

为什么 Redis 不支持回滚(roll back)

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

以下是这种做法的优点:

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

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

posted @ 2020-10-30 16:42  爱悟空  阅读(93)  评论(0编辑  收藏  举报