📫作者简介:小明java问道之路,专注于研究 Java/ Liunx内核/ C++及汇编/计算机底层原理/源码,就职于大型金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。
📫 热衷分享,喜欢原创~ 关注我会给你带来一些不一样的认知和成长。
🏆 CSDN博客专家/后端领域优质创作者/内容合伙人、InfoQ签约作者、阿里云专家/签约博主、51CTO专家 🏆
🔥如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主~
本文目录
本文导读
本文主要讲解Redis事务工作原理解析与实战,包括什么是Redis事务,Redis事务的特点,例如Redis事务没有隔离级别的概念、不保证原子性、不支持回滚事务等等,Redis事务实战的语法、实现,Redis事务执行的底层原理以及watch实现监控原理。
一、什么是Redis事务
事务本身是支持同时执行多个命令的集合。事务中的所有命令都将被序列化(串行化),在事务执行期间,队列中的命令将按顺序连续执行,其他客户端提交的命令请求将不会插入到事务执行命令序列中。
Redis事务的本质是命令的集合,同时也具有顺序性、排他性,可以一次执行多个命令。
二、Redis事务的特点
1、Redis事务没有隔离级别的概念
批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行,也就不存在事务内的查询要看到事务里的更新,事务外查询不能看到。
2、Redis不保证原子性
Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。
3、Redis 不支持回滚事务
What about rollbacks?Redis does not support rollbacks of transactions since supporting rollbacks would have a significant impact on the simplicity and performance of Redis.
https://redis.io/docs/manual/transactions/
Redis 在事务失败时不进行回滚,而是继续执行余下的命令。Redis命令只会由于语法错误或者命令使用在错误类型的键上失败。因为支持回滚会对Redis的简单性和性能产生重大影响,所有不需要对回滚进行支持,Redis 的内部可以保持简单且快速。
4、Redis事务一致性consistency
Redis事务可以确保在命令失败时回滚,数据可以恢复到执行前的状态,除非Redis进程意外终止。
5、Redis事务隔离性Isolation
Redis事务严格遵守隔离,因为Redis是单进程和单线程模式,可以确保命令执行过程不会被其他客户端命令中断。然而,Redis不像其他结构化数据库那样具有隔离级别设计。
6、Redis事务持久性Durability
Redis事务不能保证持久性。这是因为RDB和AOF在Redis持久性策略中都是异步执行的。出于性能考虑,无法保证持久性。
三、Redis事务实战
1、Redis 事务语法
一个事务从开始到执行会经历以下三个阶段:开始事务、命令入队、执行事务。
Redis提供了以下5个基本指令,MULTI、EXEC、DISCARD、WATCH、UNWATCH。
命令 |
格式 |
作用 |
返回值 |
MULTI |
MULTI |
标记一个事务块的开始。 显式开启Redis事务,后续命令将排队,等候使用EXEC进行原子执行 |
always OK. |
EXEC |
EXEC |
执行所有事务块内的命令。 执行事务中的commands队列,恢复连接状态。如果WATCH在之前被调用,只有监测中的Keys没有被修改,命令才会被执行,否则停止执行(详见下文,CAS机制) |
成功: 返回数组 —— 每个元素对应着原子事务中一个 command的返回结果; |
DISCARD |
DISCARD |
取消事务,放弃执行事务块内的所有命令。 清除事务中的commands队列,恢复连接状态。如果WATCH在之前被调用,释放监测中的Keys |
always OK. |
WATCH |
WATCH key [key ...] |
监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。 将给出的Keys标记为监测态,作为事务执行的条件 |
always OK. |
UNWATCH |
UNWATCH |
取消 WATCH 命令对所有 key 的监视。 清除事务中Keys的监测态,如果调用了EXEC或者 DISCARD,则没有必要再手动调用UNWATCH |
always OK. |
开启并执行事务
-
# 开启事务
-
MULTI
-
# 命令入队
-
set key1
1
-
set key2
2
-
# 执行事务
-
EXEC
开启并取消事务
-
# 开启事务
-
MULTI
-
# 命令入队
-
set key1
1
-
set key2
3
-
# 取消事务
-
DISCARD
-
# 观察数据未被改动
-
get key2
WATCH监控
-
# 事务开始前用WATCH监控k1
-
WATCH k1
-
set k1
11
-
-
# 开启事务
-
MULTI
-
# 修改k1值
-
set k1 v1
-
# 执行事务,发回nil,说明事务回滚
-
EXEC
-
(nil)
-
-
get k1
-
"11"
2、Redis事务实现
基于Lua脚本,Redis可以确保脚本中的命令以一次性和顺序的方式执行。同时,它不提供事务运行错误的回滚。如果某些命令在执行过程中运行不正确,其余命令将继续运行
基于中间标记变量,使用另一个标记变量来标识事务是否完成。读取数据时,首先读取标记变量以确定事务是否完成。然而,这将需要额外的代码来实现,这很麻烦
四、Redis事务执行原理
1、Redis事务执行原理
当客户端切换到事务状态时,服务器将根据客户端发送的不同命令执行不同的操作:如果客户端发送的命令是EXEC、DISCARD、WATCH和MULTI之一,服务器将立即执行该命令。
相反,如果客户端发送的命令不是EXEC、DISCARD、WATCH和MULTI,则服务器不会立即执行该命令,而是将该命令放置在事务队列中,然后向客户端返回QUEUED应答。
2、watch实现监控原理
WATCH命令可以为Redis事务提供检查和设置 check-and-set (CAS)行为。监控WATCH键,以查看它们是否已更改。
如果在执行EXEC之前至少修改了一个受监控的密钥,则整个事务将被取消。EXEC返回 nil,表示事务已失败。如果另一个客户端在WATCH之后和EXEC之前修改键值,则当前客户端的事务将失败。
程序需要做的是重试操作,直到没有冲突。这种类型的锁被称为乐观锁,在大多数情况下,不同的客户端将访问不同的密钥,并且很少发生冲突,因此通常不需要重试。
Redis 使用 WATCH 命令来决定事务是继续执行还是回滚,在这种情况下,您需要在 MULTI 之前使用WATCH监视某些键值对,然后使用 MULTI 命令启动事务并执行数据结构操作的各种命令。此时,这些命令将排队。
当EXEC用于执行事务时,它将首先比较 WATCH 监视的键值对。如果没有更改,它将执行事务队列中的命令并提交事务;如果发生更改,将不会执行事务中的任何命令,并且将回滚事务。当然,无论是否回滚,Redis 都会在事务之前取消 WATCH 命令。
总结
本文主要讲解Redis事务工作原理解析与实战,包括什么是Redis事务,Redis事务的特点,例如Redis事务没有隔离级别的概念、不保证原子性、不支持回滚事务等等,Redis事务实战的语法、实现,Redis事务执行的底层原理以及watch实现监控原理。
转载:https://blog.csdn.net/FMC_WBL/article/details/128322303