Redis 核心技术与实战
蒋德钧
中科院计算所副研究员
81696 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 53 讲
开篇词 (1讲)
实践篇 (28讲)
Redis 核心技术与实战
15
15
1.0x
00:00/00:00
登录|注册

31 | 事务机制:Redis能实现ACID属性吗?

无论采用何种持久化模式,事务的持久性属性得不到保证
Redis持久化配置模式决定数据是否持久化保存
并发操作在EXEC命令后执行,Redis单线程执行命令,保证隔离性
并发操作在EXEC命令前执行,使用WATCH机制来保证隔离性
EXEC命令执行时实例发生故障,根据RDB或AOF是否开启来保证一致性
命令入队时没报错,实际执行时报错,不改变一致性
命令入队时报错,事务被放弃执行,保证一致性
EXEC命令执行时实例故障,如果开启了AOF日志,可以保证原子性
事务中的命令语法有误时,原子性得不到保证
事务中的多个操作必须都完成或都不完成
WATCH机制
DISCARD命令
EXEC命令
MULTI命令
持久性
隔离性
一致性
原子性
事务执行过程
ACID属性
Redis事务机制

该思维导图由 AI 生成,仅供参考

你好,我是蒋德钧。
事务是数据库的一个重要功能。所谓的事务,就是指对数据进行读写的一系列操作。事务在执行时,会提供专门的属性保证,包括原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),也就是 ACID 属性。这些属性既包括了对事务执行结果的要求,也有对数据库在事务执行前后的数据状态变化的要求。
那么,Redis 可以完全保证 ACID 属性吗?毕竟,如果有些属性在一些场景下不能保证的话,很可能会导致数据出错,所以,我们必须要掌握 Redis 对这些属性的支持情况,并且提前准备应对策略。
接下来,我们就先了解 ACID 属性对事务执行的具体要求,有了这个知识基础后,我们才能准确地判断 Redis 的事务机制能否保证 ACID 属性。

事务 ACID 属性的要求

首先来看原子性。原子性的要求很明确,就是一个事务中的多个操作必须都完成,或者都不完成。业务应用使用事务时,原子性也是最被看重的一个属性。
我给你举个例子。假如用户在一个订单中购买了两个商品 A 和 B,那么,数据库就需要把这两个商品的库存都进行扣减。如果只扣减了一个商品的库存,那么,这个订单完成后,另一个商品的库存肯定就错了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Redis事务机制对ACID属性的保证是一个重要话题。本文深入探讨了Redis事务的原子性、一致性和隔离性。在原子性方面,文章指出了Redis在命令入队时报错会放弃事务执行,保证了原子性;而在实际执行时报错,不保证原子性。此外,文章还讨论了实例故障对原子性的影响,指出开启AOF日志可以保证原子性。在一致性方面,文章分析了命令入队时报错、实际执行时报错以及实例故障的情况下,Redis事务机制对一致性的保证。最后,文章提到了隔离性属性,强调了Redis事务机制对隔离性的保证。总的来说,本文对于想要了解Redis事务机制以及ACID属性的读者来说是一份很好的参考资料。文章还讨论了事务的持久性属性,指出无论Redis采用何种持久化模式,事务的持久性属性都得不到保证。Redis的事务机制可以保证一致性和隔离性,但无法保证持久性。因此,读者在使用Redis事务时需要注意严格按照Redis的命令规范进行程序开发,并通过code review确保命令的正确性,以保证多操作的正确执行。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 核心技术与实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(44)

  • 最新
  • 精选
  • 张申傲
    Redis 为什么不支持事务的回滚?可以参考下官网的解释:https://redis.io/topics/transactions

    作者回复: 官网是个非常好的学习地方 :)

    2020-12-18
    4
    11
  • 徐小熊
    我想问一下redis能否做到替代mysql作为数据来使用呢?因为redis可以使用aof日志记录命令,开启everysecond的话最多只会让一秒钟的数据丢失。如果可以接受这一秒钟丢失的数据情况的话,是不是完全可以替代mysql作为数据库啊?

    作者回复: Redis的数据模式是key-value,没有表结构,没有关系模型。MySQL是属于SQL数据库,能支持丰富的SQL查询,例如条件查询、Join查询等,而且能提供ACID保证的事务操作,这些是Redis不具备的,所以MySQL和Redis分别是面向不同的应用场景的,无法用Redis完全替代MySQL做数据库。

    2020-11-02
    7
    1
  • Kaito
    在执行事务时,如果 Redis 实例发生故障,而 Redis 使用的 RDB 机制,事务的原子性还能否得到保证? 我觉得是可以保证原子性的。 如果一个事务只执行了一半,然后 Redis 实例故障宕机了,由于 RDB 不会在事务执行时执行,所以 RDB 文件中不会记录只执行了一部分的结果数据。之后用 RDB 恢复实例数据,恢复的还是事务之前的数据。但 RDB 本身是快照持久化,所以会存在数据丢失,丢失的是距离上一次 RDB 之间的所有更改操作。 关于 Redis 事务的使用,有几个细节我觉得有必要补充下,关于 Pipeline 和 WATCH 命令的使用。 1、在使用事务时,建议配合 Pipeline 使用。 a) 如果不使用 Pipeline,客户端是先发一个 MULTI 命令到服务端,客户端收到 OK,然后客户端再发送一个个操作命令,客户端依次收到 QUEUED,最后客户端发送 EXEC 执行整个事务(文章例子就是这样演示的),这样消息每次都是一来一回,效率比较低,而且在这多次操作之间,别的客户端可能就把原本准备修改的值给修改了,所以无法保证隔离性。 b) 而使用 Pipeline 是一次性把所有命令打包好全部发送到服务端,服务端全部处理完成后返回。这么做好的好处,一是减少了来回网络 IO 次数,提高操作性能。二是一次性发送所有命令到服务端,服务端在处理过程中,是不会被别的请求打断的(Redis单线程特性,此时别的请求进不来),这本身就保证了隔离性。我们平时使用的 Redis SDK 在使用开启事务时,一般都会默认开启 Pipeline 的,可以留意观察一下。 2、关于 WATCH 命令的使用场景。 a) 在上面 1-a 场景中,也就是使用了事务命令,但没有配合 Pipeline 使用,如果想要保证隔离性,需要使用 WATCH 命令保证,也就是文章中讲 WATCH 的例子。但如果是 1-b 场景,使用了 Pipeline 一次发送所有命令到服务端,那么就不需要使用 WATCH 了,因为服务端本身就保证了隔离性。 b) 如果事务 + Pipeline 就可以保证隔离性,那 WATCH 还有没有使用的必要?答案是有的。对于一个资源操作为读取、修改、写回这种场景,如果需要保证事物的原子性,此时就需要用到 WATCH 了。例如想要修改某个资源,但需要事先读取它的值,再基于这个值进行计算后写回,如果在这期间担心这个资源被其他客户端修改了,那么可以先 WATCH 这个资源,再读取、修改、写回,如果写回成功,说明其他客户端在这期间没有修改这个资源。如果其他客户端修改了这个资源,那么这个事务操作会返回失败,不会执行,从而保证了原子性。 细节比较多,如果不太好理解,最好亲自动手试一下。
    2020-10-30
    35
    248
  • tt
    • 原子性就是一批操作,要不全部完成,要不一个也不执行。 • 原子性的结果就是中间结果对外不可见,如果中间结果对外可见,则一致性就不会得到满足(比如操作)。 • 而隔离性,指一个事务内部的操作及使用的数据对正在进行的其他事务是隔离的,并发执行的各个事务之间不能互相干扰,正是它保证了原子操作的过程中,中间结果对其它事务不可见。 本文在讨论一致性的时候,说到“ 命令入队时没报错,实际执行时报错在这种情况下,有错误的命令不会被执行,正确的命令可以正常执行,也不会改变数据库的一致性。”,我觉得这一点是存疑的,不保证原子性就保证不了一致性。比如转账操作,扣减转出账户的操作成功,增加转入账户的操作失败,则原子性和一致性都被破坏。
    2020-11-02
    12
    34
  • test
    redis开启RDB,因为RDB不会在事务执行的时候执行,所以是可以保证原子性的
    2020-10-30
    17
  • 小文同学
    1、作者讲了什么? 作者通过本文讨论,Redis 是否可以保证 ACID 的事务功能。事务是对数据进行一系列操作。 2、作者是怎么把事情说明白的? 作者先讨论 事务ACID 属性的要求:然后作者说明了 Redis 的 API :MULTI 和 EXEC 是如何完成事务的;完成说明后,作者开始针对事务的每个特性,讨论 Redis 是否已经完成达成。 2.1 原子性。原子性的保证分三种情况 2.1.1 队列中有命令存在错误,队列清空;(可保证原子) 2.1.2 队列中命令到执行的时候才被发现有错误,不会滚,执行多少算多少;(不保证原子) 2.1.3 EXEC 时, Redis 实例发生故障。这个涉及到日志,AOF 的 redis-check-aof 可以发现没执行完成的操作,进而清除;(可以保证原子) 2.2 一致性。作者分三种情况说明,并且确认都可以提供一致性。 2.3 隔离性。WATCH 机制提供事务隔离性。 2.4 持久性。Redis 任何时候都无法提供持久性保障。 3、为了讲明白,作者讲了哪些要点?哪些是亮点? 在 Redis 的事务上,作者通过 三种情况 ,分别说明了 Redis 是否满足 ACID 特性,这个划分方法是一个亮点; 4、对于作者所讲,我有哪些发散性思考? Redis 始终坚持是一个高性能的内存数据库,并没有因为事务的重要性而放弃这一个宗旨,故在内存中实现了隔离性,一致性,有条件原子性,不实现持久性。这个也可以放映出 Redis 的定位和一般数据库 MySQL 是不一样的; 5、在未来哪些场景,我可以使用它? 在高并发,竞争环境下,需要保证数据正确时,可以考虑 Redis 的事务性实现。
    2020-12-04
    1
    8
  • 与君共勉
    AOF如果开启always模式不是可以保证数据不丢失吗?为啥也保证不了持久性呢?
    2020-10-30
    5
    6
  • hello
    “错误的命令不会被执行,正确的命令可以正常执行,也不会改变数据库的一致性”这个怎么就没有改变数据库的一致性了呢?我是菜鸟一枚,有大神指点一二吗?
    2020-11-12
    4
    5
  • Lemon
    老师,我对Redis能保证一致性这点表示困惑:在命令入队时没有报错,实际执行时报错的情况下,如果A给B转账,A的账户被扣钱了,此时命令出错,B账户并没有增加转账金额,这不就导致了事务前后的数据不一致了吗?
    2020-11-02
    4
    4
  • ꧁子华宝宝萌萌哒꧂
    老师,在上一节中,分布式锁重要的就是保证操作的原子性,既然事物能保证原子性,为啥上一节中没有提到用事物来做呢?
    2020-10-30
    6
    4
收起评论
显示
设置
留言
44
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部