Redis中事务是什么

42次阅读
没有评论

共计 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 问一下细节

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-12-04发表,共计2892字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)