后端存储实战课
李玥
美团高级技术专家
44005 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 30 讲
结束语 (1讲)
后端存储实战课
15
15
1.0x
00:00/00:00
登录|注册

04 | 事务:账户余额总是对不上账,怎么办?

SERIALIZABLE级别
RR级别
RC级别
RU级别
持久性
隔离性
一致性
原子性
多个事务并发更新同一个账户时,RC和RR两种不同的隔离级别的行为差异
兼顾并发、性能和数据一致性的交易实现
幻读问题
理解事务的隔离级别
ACID四个基本特性
使用数据库事务保证数据一致性
账户流水的重要性和设计原则
冗余数据的一致性问题
业务需求分析
账户系统的功能和用途
思考题
数据库事务
事务系统设计
事务系统设计与数据库事务

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

你好,我是李玥。今天这节课我们来说一下电商的账户系统。
账户系统负责记录和管理用户账户的余额,这个余额就是每个用户临时存在电商的钱,来源可能是用户充值或者退货退款等多种途径。
账户系统的用途也非常广泛,不仅仅是电商,各种互联网内容提供商、网络游戏服务商,电信运营商等等,都需要账户系统来管理用户账户的余额,或者是虚拟货币。包括银行的核心系统,也同样包含一个账户系统。
从业务需求角度来分析,一个最小化的账户系统,它的数据模型可以用下面这张表来表示:
这个表包括用户 ID、账户余额和更新时间三个字段。每次交易的时候,根据用户 ID 去更新这个账户的余额就可以了。

为什么总是对不上账?

每个账户系统都不是孤立存在的,至少要和财务、订单、交易这些系统有着密切的关联。理想情况下,账户系统内的数据应该是自洽的。所有用户的账户余额加起来,应该等于这个电商公司在银行专用账户的总余额。账户系统的数据也应该和其他系统的数据能对的上。比如说,每个用户的余额应该能和交易系统中充值记录,以及订单系统中的订单对的上。
不过,由于业务和系统的复杂性,现实情况却是,很少有账户系统能够做到一点不差的对上每一笔账。所以,稍微大型一点儿的系统,都会有一个专门的对账系统,来核对、矫正账户系统和其他系统之间的数据差异。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了电商账户系统管理中的数据一致性问题,特别是账户余额和交易记录的冗余数据如何保持一致。作者首先介绍了数据库事务的基本特性ACID,强调了事务的重要性。随后详细讨论了MySQL提供的四种隔离级别,重点解释了可重复读和读已提交两种常用隔离级别的区别,并简要介绍了幻读的概念。最后,作者给出了一种兼顾并发、性能和数据一致性的交易实现方法。通过本文,读者可以深入了解不同业务场景下选择合适的隔离级别,以及如何实现兼顾性能和数据一致性的交易处理方式。这对于需要处理账户余额和交易记录的系统设计和开发具有重要的指导意义。文章内容涵盖了数据库事务的基本特性ACID,MySQL提供的隔离级别,以及兼顾并发、性能和数据一致性的交易实现方法,为读者提供了深入的技术指导和实践思路。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《后端存储实战课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(72)

  • 最新
  • 精选
  • 李玥
    置顶
    hi,我是李玥。 我们还是回顾一下上节课留的思考题,是这样的。 既然用户的购物车数据存放在MySQL或者是Redis中各有优劣势。那能不能把购物车数据存在MySQL中,并且用Redis来做缓存呢?这样不就可以兼顾两者的优势了么?这样做是不是可行?如果可行,如何来保证Redis中的数据和MySQL中的数据是一样的呢? 关于这个问题,我这样看。 用Redis给购物车库做缓存,技术上肯定是可行的。但是有两个问题需要思考一下。 第一个问题是,值不值得这样做?因为每个人的购物车都是不一样的,所以这个缓存它的读写比差距不会很大,缓存的命中率不会太高,缓存的收益有限,为了维护缓存,还要增加系统的复杂度。所以我们就要自行权衡一下,是不是值得的问题。我的观点是,除了超大规模的系统以外,没有必要设置这个缓存。 第二个问题是,如果我们非要做这样一个缓存,用什么缓存更新策略更好呢?这里我先卖个关子,在《11 | MySQL如何应对高并发(一):使用缓存保护MySQL》这节课中,我们会专门讲到几种常用的缓存策略,你可以学完这节课之后,再回过头来想一下这个问题。
    2020-03-05
    2
    72
  • Zend
    老师,针对余额更新这种场景,我们是不是就应该用RC隔离级别,因为RR隔离级别会不会存在余额已经被别的事务更新了,而当前事务还是用旧数据。

    作者回复: 所以我们要加上余额流水的ID来控制并发更新,这样无论是rc还是rr都是安全的。

    2020-03-11
    10
    21
  • 乖,摸摸头
    这里 使用 version 和 select for update 都能解决问题,请问 李sir 实际场合种哪一种更合适

    作者回复: 我们一直说,要分析具体的场景,选择合适的方法。所以,要先有场景,才谈得上选择。 如果有一种方法或技术在各种场景下都优于另外一种,另外一种早就被淘汰了,不会出现在大家的视野中。

    2020-05-11
    14
  • E
    LAST_INSERT_ID() 这个可以保证是事务里最后插入的那个id吗 会遇到是其他事务产生的id吗

    作者回复: 这个是和Session绑定的,所以不会有并发问题。

    2020-03-13
    4
    9
  • 全麦小面包
    我是java开发者,像JPA框架是不提供更新的影响行数的,那该怎么办呢?

    作者回复: JPA是可以返回更新行数的,你让接口更新方法的定义的返回值是int类型,返回的数值就是更新行数。

    2020-03-06
    8
  • Wisee
    这种适合单库的操作,如果是业务量大了,分库分表了,就不能这么做了吧

    作者回复: 是的,后面我们也会讲到分库分表

    2020-03-19
    6
  • 要是更新余额(假设mysql)、记录流水(假设mongo)不是同一个存储设备,如何使用事务保证同时成功或同时失败?

    作者回复: 请继续学习下一节课,分布式事务。

    2020-03-12
    4
  • 想知道大厂还用事务吗,或者像银行转账,会用事务吗?分布式微服务不适合事务吧,是否做补偿机制就好呢,比如搞个定时任务定时check再修复数据

    作者回复: 在线交易系统中,用事务解决数据一致性问题还是主流的方法。大厂也是一样的。

    2020-04-05
    3
  • 白不吃
    我有个疑问,对于mysql innodb来说,一个事物(线程)操作数据的时候不是会直接锁行么,另一个事物(线程)不是会处于阻塞等待中么?

    作者回复: 会的。

    2020-03-12
    2
    3
  • suke
    老师,那更新失败的情况一般电商系统该如何处理?是要继续尝试?还是直接返回失败

    作者回复: 一般交易类系统如果出现失败,建议的做法是回滚并返回失败。

    2020-03-05
    5
    3
收起评论
显示
设置
留言
72
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部