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

12 | MySQL如何应对高并发(二):读写分离

解决主从延迟带来的数据不一致问题
主从同步延迟可能导致数据不一致的情况
代理方式
组件方式
纯手工方式
分离应用程序对数据库的读写请求,分别发送给从库和主库
部署一主多从多个MySQL实例,并让它们之间保持数据实时同步
小结
注意读写分离带来的数据不一致问题
读写分离的实施方式
实施MySQL的读写分离方案
读写分离架构示意图
读写比例严重不均衡,大部分请求是只读查询请求
分布式存储系统中,分布式写难以实现,但分布式读相对简单
单台MySQL无法满足要求时,使用多个MySQL实例来承担大量的读写请求
思考题
读写分离是提升MySQL并发的首选方案
读写分离
MySQL如何应对高并发

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

你好,我是李玥。
上节课我和你讲了,使用 Redis 作为 MySQL 的前置缓存,可以帮助 MySQL 挡住绝大部分的查询请求。这种方法对于像电商中的商品系统、搜索系统这类与用户关联不大的系统,效果特别的好。因为在这些系统中,每个人看到的内容都是一样的,也就是说,对后端服务来说,每个人的查询请求和返回的数据都是一样的。这种情况下,Redis 缓存的命中率非常高,近乎于全部的请求都可以命中缓存,相对的,几乎没有多少请求能穿透到 MySQL。
但是,和用户相关的系统,使用缓存的效果就没那么好了,比如说,订单系统、账户系统、购物车系统等等。在这些系统里面,每个用户需要查询的信息都是和用户相关的,即使是同一个功能界面,那每个人看到的数据都是不一样的。
比如说,“我的订单”这个功能,用户在这里看到的都是自己的订单数据,我打开我的订单缓存的数据,是不能给你打开你的订单来使用的,因为我们两个人的订单是不一样的。这种情况下,缓存的命中率就没有那么高,还是有相当一部分查询请求因为命中不了缓存,打到 MySQL 上。
那随着系统用户数量越来越多,打到 MySQL 上的读写请求也越来越多,当单台 MySQL 支撑不了这么多的并发请求时,我们该怎么办?
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

MySQL高并发处理的关键方案之一是读写分离。通过将读请求和写请求分发到不同的MySQL实例上,可以有效减轻单台MySQL的压力,提升系统的并发处理能力。读写分离的实施方式包括部署一主多从的MySQL实例,并使用读写分离组件来分离应用程序对数据库的读写请求。这种方案能够简单而有效地提升数据库支持的并发数量,但需要注意主从同步延迟可能带来的数据不一致问题。因此,在设计业务逻辑时,需要尽量规避在更新数据后立即去查询更新后的数据,以克服主从同步延迟可能带来的数据不一致情况。总的来说,读写分离是一个可行的存储架构升级方案,能够显著提升系统的并发处理能力,但需要在业务逻辑设计上加以规避主从同步延迟可能带来的数据不一致问题。

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

全部留言(32)

  • 最新
  • 精选
  • 李玥
    置顶
    Hi,我是李玥。 这里回顾一下上节课的思考题: 课后请你想一下,具体什么情况下,使用Cache Aside模式更新缓存会产生脏数据?欢迎你在评论区留言,通过一个例子来说明情况。 说一种可能产生脏数据的情况: 使用Cache Aside模式来更新缓存,是不是就完全可以避免产生脏数据呢?也不是,如果一个写线程在更新订单数据的时候,恰好赶上这条订单数据缓存过期,又恰好赶上一个读线程正在读这条订单数据,还是有可能会产生读线程将缓存更新成脏数据。但是,这个可能性相比Read/Write Through模式要低很多,并且发生的概率并不会随着并发数量增多而显著增加,所以即使是高并发的场景,这种情况实际发生的概率仍然非常低。 既然不能百分之百的避免缓存的脏数据,那我们可以使用一些方式来进行补偿。比如说,把缓存的过期时间设置的相对短一些,一般在几十秒左右,这样即使产生了脏数据,几十秒之后就会自动恢复了。更复杂一点儿的,可以在请求中带上一个刷新标志位,如果用户在查看订单的时候,手动点击刷新,那就不走缓存直接去读数据库,也可以解决一部分问题。
    2020-03-24
    5
    28
  • 王佳山
    这篇文章中提到的同一个事务会路由到主库是什么意思?

    作者回复: 比如先后执行一条更新语句,和一条查询语句。 默认读写分离的情况下,更新语句会走主库,查询语句会走从库。 如果把这两条语句放到同一个事务里面,因为事务的原子性,那查询语句也会走主库。

    2020-06-15
    4
    21
  • 上山砍柴
    老师您好!读写分离后,是否可以满足高并发写呢,比如秒杀系统,能够满足瞬间大量订单创建写数据库吗?

    作者回复: 即使做了读写分离,一般也不会用MySQL直接抗秒杀请求,还是需要前置保护机制,避免大量的请求打到MySQL上。

    2020-04-05
    6
  • 安排
    HAproxy keepalived是和mysql部署在同一台机器上的吗?还是部署在单独的机器上的?

    作者回复: 部署在一起。

    2020-03-24
    6
  • Aliliin
    在上家公司,我记得我写订单支付成功之后需要送优惠券的业务,也导致赠送优惠券不成功。 测试环境怎么都不出问题,后来才想到的是主从的问题,之后就修改成功了,从主库查询并增加优惠券。忙到半夜。这个课程真是太好了。
    2020-03-24
    3
    33
  • Mongo
    - Redis作为 MySQL前置 针对类似电商类看到的结果是一样的效果很好 针对看到的内容各不相同的时候,效果一般 - MySQL 针对高并发方案 - 分布式存储系统难点 写难以保证数据一致性 分布式读相对简单 - 构建分布式集群 不建议构建分布式集群,代价大 - 读写分离方案 读写分离,可有效分担大量的查询请求 读写分离,实施比较方便 - 读写分离方案 部署一主多从多个 MySQL 实例,并让他们之间保持数据实时同步 分离应用程序对数据库的读写请求,分别发送到从库和主库 - 分离读写的方法(推荐第二种) 1.纯手工方式:修改应用程序 DAO 层代码,定义读写两个数据源,指定每一个数据库请求的数据源 2.组件方式:也可以使用像 Sharding-JDBC这种集成在应用中的第三方组件来实现,这些组件集成在你的应用程序内,代理应用程序的所有数据库请求,自动把请求路由到对应数据库实例上 3.代理方式:在应用程序和数据库实例之间部署一组数据库代理实例, 比如 Atlas 或者 MaxScale。对应用程序来说,数据库代理把自己伪装成一个单节点的 MySQL 实例,应用程序的诉讼有数据库请求被发送到给代理,代理分离读写请求,然后转发给对应的数据库实例。 - 配置多个从库 推荐使用"HAProxy + Keeplived"组合 - 读写分离弊端 可能导致数据不一致的问题,正常不超过1ms - 解决方法 将同步的一些操作放到一个数据库事务中来做,写与读在一个库 增加一些步骤操作,让 1ms 的同步自然的消耗掉
    2020-03-27
    17
  • kyll
    原来用mycat,现在我们使用sharding-jdbc,配置简单,对开发透明。而且看官网上未来发展前景不错。sharding可以做到同一个线程内更新后的查询在主库进行,其他的情况也是在交互上做改进了
    2020-03-25
    15
  • 夜空中最亮的星
    电商直接提示,订单稍后查询😄
    2020-03-24
    10
  • leslie
    HAProxy+Keepalived这套架构:挺好挺稳定,业界使用率很高。 偷懒点可以直接用云厂商,不过读写分离的能力确实不敢恭维。
    2020-03-25
    2
    6
  • 怀朔
    现在主流的都是用proxy的 主备延迟怎么解决呢? 1、开启半同步方案 2、尽量在主库里面减少大事务、使用不均匀的话开启写后考虑主库读 3、有能力的话 分库分表 4、增加从库性能 5、如果实在无法追平 从新做从库吧
    2020-03-24
    4
收起评论
显示
设置
留言
32
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部