详细了解Redis中的事务
本篇文章带大家详细了解一下Redis中的事务。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。
【相关推荐:Redis视频教程】
相关命令
命令 | 格式 | 作用 | 返回结果 |
---|---|---|---|
WATCH | WATCH key [key ...] | 将给出的Keys 标记为监测态 ,作为事务执行的条件 |
always OK. |
UNWATCH | UNWATCH | 清除事务中Keys 的 监测态 ,如果调用了EXEC or DISCARD,则没有必要再手动调用UNWATCH
|
always OK. |
MULTI | MULTI |
显式 开启redis事务 ,后续commands 将排队,等候使用EXEC进行原子执行 |
always OK. |
EXEC | EXEC | 执行事务中的commands 队列,恢复连接状态。如果WATCH在之前被调用,只有监测 中的Keys 没有被修改,命令才会被执行,否则停止执行(详见下文,CAS机制 ) |
成功: 返回数组 —— 每个元素对应着原子事务中一个 command 的返回结果;失败: 返回 NULL (Ruby 返回`nil` ); |
DISCARD | DISCARD | 清除事务中的commands 队列,恢复连接状态。如果WATCH在之前被调用,释放 监测 中的Keys
|
always 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 OK >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 +OK >INCR a b c -ERR wrong number of arguments for 'incr' command
这是由于
INCR
命令的语法错误,将在调用EXEC
之前被检测出来,并终止事务(version2.6.5+)。
- 在调用
EXEC
命令之后出现错误。 - 例如,使用
错误的值
对某个key
执行操作(如针对String
值调用List
操作)
EXEC
命令执行之后发生的错误并不会被特殊对待:即使事务中的某些命令执行失败,其他命令仍会被正常执行
。
- 示例如下:
>MULTI +OK >SET a 3 +QUEUED >LPOP a +QUEUED >EXEC *2 +OK -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 OK > MULTI OK > INCR foo QUEUED > DISCARD OK > GET foo "1"
更多编程相关知识,请访问:编程视频!!
以上是详细了解Redis中的事务的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

Redis集群模式通过分片将Redis实例部署到多个服务器,提高可扩展性和可用性。搭建步骤如下:创建奇数个Redis实例,端口不同;创建3个sentinel实例,监控Redis实例并进行故障转移;配置sentinel配置文件,添加监控Redis实例信息和故障转移设置;配置Redis实例配置文件,启用集群模式并指定集群信息文件路径;创建nodes.conf文件,包含各Redis实例的信息;启动集群,执行create命令创建集群并指定副本数量;登录集群执行CLUSTER INFO命令验证集群状态;使

使用 Redis 指令需要以下步骤:打开 Redis 客户端。输入指令(动词 键 值)。提供所需参数(因指令而异)。按 Enter 执行指令。Redis 返回响应,指示操作结果(通常为 OK 或 -ERR)。

如何清空 Redis 数据:使用 FLUSHALL 命令清除所有键值。使用 FLUSHDB 命令清除当前选定数据库的键值。使用 SELECT 切换数据库,再使用 FLUSHDB 清除多个数据库。使用 DEL 命令删除特定键。使用 redis-cli 工具清空数据。

Redis 使用单线程架构,以提供高性能、简单性和一致性。它利用 I/O 多路复用、事件循环、非阻塞 I/O 和共享内存来提高并发性,但同时存在并发性受限、单点故障和不适合写密集型工作负载的局限性。

理解 Redis 源码的最佳方法是逐步进行:熟悉 Redis 基础知识。选择一个特定的模块或功能作为起点。从模块或功能的入口点开始,逐行查看代码。通过函数调用链查看代码。熟悉 Redis 使用的底层数据结构。识别 Redis 使用的算法。

要查看 Redis 中的所有键,共有三种方法:使用 KEYS 命令返回所有匹配指定模式的键;使用 SCAN 命令迭代键并返回一组键;使用 INFO 命令获取键的总数。

Redis 使用哈希表存储数据,支持字符串、列表、哈希表、集合和有序集合等数据结构。Redis 通过快照 (RDB) 和追加只写 (AOF) 机制持久化数据。Redis 使用主从复制来提高数据可用性。Redis 使用单线程事件循环处理连接和命令,保证数据原子性和一致性。Redis 为键设置过期时间,并使用 lazy 删除机制删除过期键。

要从 Redis 读取队列,需要获取队列名称、使用 LPOP 命令读取元素,并处理空队列。具体步骤如下:获取队列名称:以 "queue:" 前缀命名,如 "queue:my-queue"。使用 LPOP 命令:从队列头部弹出元素并返回其值,如 LPOP queue:my-queue。处理空队列:如果队列为空,LPOP 返回 nil,可先检查队列是否存在再读取元素。
