共计 2892 个字符,预计需要花费 8 分钟才能阅读完成。
自动写代码机器人,免费开通
这篇文章主要介绍 Redis 中事务是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
相关命令命令格式作用返回结果 WATCHWATCH key [key …] 将给出的 Keys 标记为监测态,作为事务执行的条件 always OK.UNWATCHUNWATCH 清除事务中 Keys 的 监测态,如果调用了 EXEC or DISCARD,则没有必要再手动调用 UNWATCHalways OK.MULTIMULTI 显式开启 redis 事务,后续 commands 将排队,等候使用 EXEC 进行原子执行 always OK.EXECEXEC 执行事务中的 commands 队列,恢复连接状态。如果 WATCH 在之前被调用,只有监测中的 Keys 没有被修改,命令才会被执行,否则停止执行(详见下文,CAS 机制)成功:返回数组 —— 每个元素对应着原子事务中一个 command 的返回结果;
失败:返回 NULL(Ruby 返回 `nil`);DISCARDDISCARD 清除事务中的 commands 队列,恢复连接状态。如果 WATCH 在之前被调用,释放 监测中的 Keysalways OK.
注意:
——MULTI,EXEC,DISCARD 才是显式开启并控制事务的常用命令,可类比关系型数据库中的 BEGAIN,COMMIT,ROLLBACK(事实上,差距很大);
——WATCH 命令的使用是为了解决 事务并发 产生的不可重复读和幻读的问题(简单理解为给 Key 加锁);
Redis 事务
MULTI, EXEC, DISCARD and WATCH 是 Redis 事务的基础。用来显式开启并控制一个事务,它们允许在一个步骤中执行一组命令。并提供两个重要的保证:
事务中的所有命令都会被序列化并按顺序执行。在执行 Redis 事务的过程中,不会出现由另一个客户端发出的请求。这保证 命令队列 作为一个单独的原子操作被执行。
队列中的命令要么全部被处理,要么全部被忽略。EXEC 命令触发事务中所有命令的执行,因此,当客户端在事务上下文中失去与服务器的连接,
如果发生在调用 MULTI 命令之前,则不执行任何 commands;
如果在此之前 EXEC 命令被调用,则所有的 commands 都被执行。
同时,redis 使用 AOF(append-only file),使用一个额外的 write 操作将事务写入磁盘。如果发生宕机,进程奔溃等情况,可以使用 redis-check-aof tool 修复 append-only file,使服务正常启动,并恢复部分操作。
用法
使用 MULTI 命令显式开启 Redis 事务。该命令总是以 OK 回应。此时用户可以发出多个命令,Redis 不会执行这些命令,而是将它们排队。EXEC 被调用后,所有的命令都会被执行。而调用 DISCARD 可以清除事务中的 commands 队列并退出事务。
以下示例以原子方式,递增键 foo 和 bar。
MULTI
INCR foo
QUEUED
INCR bar
QUEUED
EXEC
1)(整数)1
2)(整数)1
从上面的命令执行中可以看出,EXEC 返回一个数组,其中每个元素都是事务中单个命令的返回结果,而且顺序与命令的发出顺序相同。
当 Redis 连接处于 MULTI 请求的上下文中时,所有命令将以字符串 QUEUED(从 Redis 协议的角度作为状态回复发送)作为回复,并在命令队列中排队。只有 EXEC 被调用时,排队的命令才会被执行,此时才会有真正的返回结果。
事务中的错误
事务期间,可能会遇到两种命令错误:
在调用 EXEC 命令之前出现错误(COMMAND 排队失败)。
例如,命令可能存在语法错误(参数数量错误,错误的命令名称 …);
或者可能存在某些关键条件,如内存不足的情况(如果服务器使用 maxmemory 指令做了内存限制)。
客户端会在 EXEC 调用之前检测第一种错误。通过检查排队命令的状态回复(*** 注意:这里是指排队的状态回复,而不是执行结果 ***),如果命令使用 QUEUED 进行响应,则它已正确排队,否则 Redis 将返回错误。如果排队命令时发生错误,大多数客户端将中止该事务并清除命令队列。然而:
在 Redis 2.6.5 之前,这种情况下,在 EXEC 命令调用后,客户端会执行命令的子集(成功排队的命令)而忽略之前的错误。
从 Redis 2.6.5 开始,服务端会记住在累积命令期间发生的错误,当 EXEC 命令调用时,将拒绝执行事务,并返回这些错误,同时自动清除命令队列。
示例如下:
MULTI
INCR a b c
-ERR wrong number of arguments for incr command
这是由于 INCR 命令的语法错误,将在调用 EXEC 之前被检测出来,并终止事务(version2.6.5+)。
在调用 EXEC 命令之后出现错误。
例如,使用错误的值对某个 key 执行操作(如针对 String 值调用 List 操作)
EXEC 命令执行之后发生的错误并不会被特殊对待:即使事务中的某些命令执行失败,其他命令仍会被正常执行。
示例如下:
MULTI
SET a 3
+QUEUED
LPOP a
+QUEUED
EXEC
-ERR Operation against a key holding the wrong kind of value
EXEC 返回一个包含两个元素的字符串数组,一个元素是 OK,另一个是 -ERR……。
能否将错误合理的反馈给用户这取决于客户端 library(如:Spring-data-redis.redisTemplate) 的自身实现。
需要注意的是,即使命令失败,队列中的所有其他命令也会被处理 —-Redis 不会停止命令的处理。
Redis 事务不支持 Rollback(重点)
事实上 Redis 命令在事务执行时可能会失败,但仍会继续执行剩余命令而不是 Rollback(事务回滚)。如果你使用过关系数据库,这种情况可能会让你感到很奇怪。然而针对这种情况具备很好的解释:
Redis 命令可能会执行失败,仅仅是由于错误的语法被调用(命令排队时检测不出来的错误),或者使用错误的数据类型操作某个 Key:这意味着,实际上失败的命令都是编程错误造成的,都是开发中能够被检测出来的,生产环境中不应该存在。(这番话,彻底甩锅,“都是你们自己编程错误,与我们无关”。)
由于不必支持 Rollback,Redis 内部简洁并且更加高效。
“如果错误就是发生了呢?”这是一个反对 Redis 观点的争论。然而应该指出的是,通常情况下,回滚并不能挽救编程错误。鉴于没有人能够挽救程序员的错误,并且 Redis 命令失败所需的错误类型不太可能进入生产环境,所以我们选择了不支持错误回滚(Rollback)这种更简单快捷的方法。
清除命令队列
DISCARD 被用来中止事务。事务中的所有命令将不会被执行, 连接将恢复正常状态。
SET foo 1
MULTI
INCR foo
QUEUED
DISCARD
GET foo
1
以上是“Redis 中事务是什么”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注丸趣 TV 行业资讯频道!
向 AI 问一下细节