Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

字节一面:了解Redis的事务吗?它的命令有哪些?它和MySQL的事务有什么区别?

MySQL 事务

mysql的事务主要要4个特点,也就是ACID,这是面试常问到的点

Atomicity(原子性):事务中的操作要么全部执行,要么全部不执行

Consistency(一致性):事务执行前后,数据库中数据在逻辑上都是正确的。常举的例子是,A给B转100块,执行前A的账户有a元,B的账户有b元,执行后A的账户是a-100, b的账户 b+100,这就是一致性。

Isolation(独立性):数据库中的事务的执行是相互不干扰的

Durability(持久性):事务执行完后,结果是永久生效的,就算断电后重启也是生效的

Redis事务

Redis官方文档对事务的描述如下图所示

image-20250426164142815

总结:Redis的事务指的是使用核心命令,例如 MULTI, EXEC,DSICARD, WATCH,让一组命令在一个单步中顺序执行。

让我们来一个一个看每个命令的作用

MULTI

image-20250426164831477

官方文档的描述是:MULTI标记了一组命令的开始,它标记了一个事务的执行入口,这组命令按照加入的顺序进行排放,使用了MULTI命令后,后续的命令不会被执行,直到执行EXEC命令时,这组命令就会按照顺序执行

image-20250426174342994

可以看出,当我们输入MULTI时,后续输入的命令不会被立刻执行,而是放进了队列里,成功将命令放进队列时会返回 QUEUED 字符串标志

EXEC

image-20250426165330323)

官方文档描述:调用EXEC命令时,Redis会按照顺序执行MULTI之后入队的所有命令。

如果使用了WATCH命令,相当于实现一个【乐观锁】,监控一个或多个键值的变化。这些键值没有被改变才能执行事务,否则不执行事务

image-20250426174511574

WATCH

image-20250426165921989

官方文档描述:调用 WATCH 命令监听多个键值的变化,作为判断能否执行事务的条件。如果在执行事务前或期间监听的键值对发生变化,那么放弃执行事务

image-20250426175408525

image-20250426175553534

UNWATCH

image-20250426170300069

官方文档描述:清空当前连接中所有被 WATCH 监听的键,取消对这些键的乐观锁监控。

image-20250426181342721

DISCARD

image-20250426170422025

官方文档描述:

  1. 清空事务队列
    取消当前连接中所有通过 MULTI 入队的命令,使连接退出事务状态,恢复正常执行模式。
  2. 自动释放 WATCH 监听
    如果事务开始前调用了 WATCHDISCARD自动清除所有被监听的键(效果等同于 UNWATCH

image-20250426181511097

MULTI创建一个队列,输入一组命令,然后输入 DISCARD, 当执行 EXEC 时,返回错误提示信息:没有可执行的事务。

除了Redis这些特有的命令,Redis的事务的最大特点是什么?

Redis如何处理事务执行过程中发生的错误

还是来看一下官方文档

image-20250426171331084

官方文档表述:在执行一个事务的时候,可能会在两个地方发生错误

第一处:调用MULTI命令时, 命令入队列错误(可能因为语法、参数等错误)。

redis 2.6.5之前的版本和之后的版本,对于第一处错误有不同的处理方式,2.6.5之后的版本会对入队列的命令进行一个检测,如果检测到有错误,会拒绝执行事务,调用EXEC命令时返回错误。

redis2.6.5之前的版本,在入队列时检测错误,如果有错误,由客户端决定是否是继续执行事务还是放弃事务

第二处:执行EXEC时命令执行错误

redis的特点是,队列中的命令执行失败了,并不会影响它后面命令的执行,这和MySql有很大的区别

Redis有回滚吗?为什么?

image-20250426185038838

官方文档解释:Redis是不支持回滚操作的,这是为了保证Redis的简单性和高性能。

image-20250426173820962

尝试一下创建一个事务,这个事务包含4条命令,第三条命令是错误的,他们都成功入队列了,当执行EXEC时,可以发现,第三条命令失败了,但是第四条命令可以执行成功。验证了redis事务中的命令执行失败并不会影响其它命令的执行。

得出结论: redis的事务不保证命令全部执行正确,它只保证一系列命令执行的原子性。

我们来分析一下,为什么redis不支持回滚操作

redis 的设计思想:简单、高效!事务回滚是复杂的,违背设计原则

  1. redis 的问题设计初衷是简单高效,事务回滚会增加复杂性

  2. redis 的单线程模型让命令执行是串行的,天然不需要处理多线程并发带来的事务回滚操作

  3. 事务中的错误通常是语法错误,应该在开发阶段解决,而不是在运行时回滚

  4. 事务回滚必然要维护旧的数据状态,但是redis 是简单高效的缓存,不是强一致性的数据库

  5. redis 是内存数据库,选择牺牲回滚能力换取更高的吞吐能力

评论