Redis事务允许对多个命令进行分组并顺序执行。 整个交易状态与其他用户隔离,并且在提交交易后便可见。
Redis事务与关系数据库中的事务不同。 Redis事务感觉更像是命令队列/堆栈,因为命令已排队并且执行推迟了。 对于读写来说是这样。 真正的惊喜是读取命令,因为任何返回值仅在事务执行时返回。
Redis事务的特长是Redis事务可以有条件地进行。 条件事务允许使用检查并设置乐观锁定。 有条件交易监视一个或多个密钥。 如果在事务之外更改了监视的键之一,则该事务将被丢弃。
使用四个命令控制事务,这些事务位于连接范围内:
-
MULTI
:发起交易 -
EXEC
:执行排队的命令 -
DISCARD
:丢弃排队的命令并退出事务模式(称为回滚) -
WATCH
:关注变革的关键因素,并进行以下交易条件。 在发出MULTI
命令之前执行MULTI
-
UNWATCH
:重置按键的监视状态。
发出MULTI
命令后,即可在事务中执行Redis命令。
> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1
该命令序列说明了redis-cli
上的事务。 使用MULTI
关键字启动事务,两个INCR
命令排队等待不同的密钥。 使用EXEC
执行事务时,将返回命令的结果。
事务中的命令获得两个响应。 在将命令发送到Redis时QUEUED
响应一个。 执行事务后,将返回第二个响应,即真值或命令响应。
对于用户来说这可能很奇怪,因为他们希望在执行命令时读命令会返回该值。 而是推迟执行,而QUEUED
是在事务中执行命令时对命令的立即响应。
Redis Standalone,Master-Slave和Sentinel
Redis中的事务绑定到特定节点。 除非复制到从节点上,否则节点上发生的所有事情都保留在该节点上。 从站设置受益于复制,因此结果被复制到从站。 无论您使用自配置的Redis主从服务器还是Redis节点是否由Redis Sentinel管理,行为上都没有区别。 除此之外,当涉及集群时,没有事务协调器。
Redis集群
Redis集群中的事务是另一回事。 在Redis群集中,特定节点是一个或多个哈希槽的主节点,这是在多个节点之间分片数据的分区方案。 根据命令中使用的键计算得出的一个哈希槽位于一个节点上。 具有多个键的命令被限制为产生相同的哈希槽。 否则,它们将被拒绝。 这样的星座被称为交叉时隙。
事务似乎是执行命令来交叉插入密钥的解决方案,但是在某个时候,一个事务将离开一个节点的范围,并且需要另一个节点来继续事务。 如果一个密钥位于一个节点上,而另一个密钥位于另一个节点上,则可能是这种情况。 仍然没有事务协调,这有时可能是Redis Cluster问题的问题。
为Redis Cluster提供事务支持的高级API面临多个问题,到目前为止,有两种策略,即如何在Redis Cluster中处理事务:
如果所有密钥都位于一个节点上,则支持交易
此选项允许功能齐全的事务。 要求客户端库跟踪事务执行的节点,并在事务进行期间禁止插槽范围之外的键。 由于只能通过使用包含密钥的命令来确定插槽,因此客户端需要设置事务标记,并且在包含密钥的第一个命令上,就需要在事务中的第一个命令之前发出MULTI命令。 显然,这里的限制是要求所有密钥都位于一个节点上。
分布式交易
在这种情况下,将在加入分布式事务的所有节点上启动多个事务。 该分布式事务可以包括来自所有主节点的密钥。 一旦执行了事务,客户端库就会触发事务的执行,该库会收集所有结果(以保持命令结果的顺序)并将其返回给调用方。
这种交易方式对客户透明。 一旦请求了特定节点上的密钥,并且该节点尚未成为事务的一部分,则发出MULTI
命令以将该节点加入事务。 此处的缺点是事务不再可以是有条件的( WATCH
)。 单个事务不知道密钥是否已在其他节点上更改,因此一个事务可以回滚,而其他事务将成功。 听起来有点像两阶段提交。
结论
Redis Transactions感觉就像可以有条件地进行原子命令批处理。 重要的是要记住,命令执行被延迟了,因为读取结果在事务执行时而不是在命令发出时返回。
对于Redis Cluster,客户尚未决定采用全球策略。 在特定的Redis群集节点上运行事务是安全的,但仅限于该节点提供的密钥。 两种可能的策略都具有对某些用例有用的属性,但也有局限性。
翻译自: https://www.javacodegeeks.com/2016/02/redis-transactions.html