0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

架构师居然这么设计DB+缓存

jf_ro2CN3Fa 来源:楼仔 作者:楼仔 2022-10-10 16:24 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

来源:楼仔

不好的方案

1. 先写 MySQL,再写 Redis

2. 先写 Redis,再写 MySQL

3. 先删除 Redis,再写 MySQL

好的方案

5. 先写 MySQL,再删除 Redis

6. 先写 MySQL,通过 Binlog,异步更新 Redis

几种方案比较

大家好,这个问题很早之前我就遇到过,但是一直没有仔细去研究,上个月看了极客的课程,有一篇文章专门有过讲解,所以感觉有必要单独出一篇。

我直接先抛一下结论:在满足实时性的条件下,不存在两者完全保存一致的方案,只有最终一致性方案。 根据网上的众多解决方案,总结出 6 种,直接看目录:

05019796-3750-11ed-ba43-dac502259ad0.png

不好的方案

1. 先写 MySQL,再写 Redis

0512eda2-3750-11ed-ba43-dac502259ad0.png

图解说明:

这是一副时序图,描述请求的先后调用顺序;

橘黄色的线是请求 A,黑色的线是请求 B;

橘黄色的文字,是 MySQL 和 Redis 最终不一致的数据;

数据是从 10 更新为 11;

后面所有的图,都是这个含义,不再赘述。

请求 A、B 都是先写 MySQL,然后再写 Redis,在高并发情况下,如果请求 A 在写 Redis 时卡了一会,请求 B 已经依次完成数据的更新,就会出现图中的问题。

这个图已经画的很清晰了,我就不用再去啰嗦了吧,不过这里有个前提,就是对于读请求,先去读 Redis,如果没有,再去读 DB,但是读请求不会再回写 Redis。 大白话说一下,就是读请求不会更新 Redis。

2. 先写 Redis,再写 MySQL

052753dc-3750-11ed-ba43-dac502259ad0.png

同“先写 MySQL,再写 Redis”,看图可秒懂。

3. 先删除 Redis,再写 MySQL

这幅图和上面有些不一样,前面的请求 A 和 B 都是更新请求,这里的请求 A 是更新请求,但是请求 B 是读请求,且请求 B 的读请求会回写 Redis。

05385380-3750-11ed-ba43-dac502259ad0.png

请求 A 先删除缓存,可能因为卡顿,数据一直没有更新到 MySQL,导致两者数据不一致。

这种情况出现的概率比较大,因为请求 A 更新 MySQL 可能耗时会比较长,而请求 B 的前两步都是查询,会非常快。

好的方案

4. 先删除 Redis,再写 MySQL,再删除 Redis

对于“先删除 Redis,再写 MySQL”,如果要解决最后的不一致问题,其实再对 Redis 重新删除即可,这个也是大家常说的“缓存双删”。

054369a0-3750-11ed-ba43-dac502259ad0.png

为了便于大家看图,对于蓝色的文字,“删除缓存 10”必须在“回写缓存10”后面,那如何才能保证一定是在后面呢?网上给出的第一个方案是,让请求 A 的最后一次删除,等待 500ms。

对于这种方案,看看就行,反正我是不会用,太 Low 了,风险也不可控。

那有没有更好的方案呢,我建议异步串行化删除,即删除请求入队列

054eca98-3750-11ed-ba43-dac502259ad0.png

异步删除对线上业务无影响,串行化处理保障并发情况下正确删除。

如果双删失败怎么办,网上有给 Redis 加一个缓存过期时间的方案,这个不敢苟同。个人建议整个重试机制,可以借助消息队列的重试机制,也可以自己整个表,记录重试次数 ,方法很多。

简单小结一下:

“缓存双删”不要用无脑的 sleep 500 ms;

通过消息队列的异步&串行,实现最后一次缓存删除;

缓存删除失败,增加重试机制。

5. 先写 MySQL,再删除 Redis

055dbc60-3750-11ed-ba43-dac502259ad0.png

对于上面这种情况,对于第一次查询,请求 B 查询的数据是 10,但是 MySQL 的数据是 11,只存在这一次不一致的情况,对于不是强一致性要求的业务,可以容忍。 (那什么情况下不能容忍呢,比如秒杀业务、库存服务等。)

当请求 B 进行第二次查询时,因为没有命中 Redis,会重新查一次 DB,然后再回写到 Reids。

056a71da-3750-11ed-ba43-dac502259ad0.png

这里需要满足 2 个条件:

缓存刚好自动失效;

请求 B 从数据库查出 10,回写缓存的耗时,比请求 A 写数据库,并且删除缓存的还长。

对于第二个条件,我们都知道更新 DB 肯定比查询耗时要长,所以出现这个情况的概率很小,同时满足上述条件的情况更小。

6. 先写 MySQL,通过 Binlog,异步更新 Redis

这种方案,主要是监听 MySQL 的 Binlog,然后通过异步的方式,将数据更新到 Redis,这种方案有个前提,查询的请求,不会回写 Redis。

057bab30-3750-11ed-ba43-dac502259ad0.png

这个方案,会保证 MySQL 和 Redis 的最终一致性,但是如果中途请求 B 需要查询数据,如果缓存无数据,就直接查 DB;如果缓存有数据,查询的数据也会存在不一致的情况。

所以这个方案,是实现最终一致性的终极解决方案,但是不能保证实时性。

几种方案比较

我们对比上面讨论的 6 种方案:

先写 Redis,再写 MySQL

这种方案,我肯定不会用 ,万一 DB 挂了,你把数据写到缓存,DB 无数据,这个是灾难性的;

我之前也见同学这么用过,如果写 DB 失败,对 Redis 进行逆操作,那如果逆操作失败呢,是不是还要搞个重试?

先写 MySQL,再写 Redis

对于并发量、一致性要求不高的项目,很多就是这么用的 ,我之前也经常这么搞,但是不建议这么做;

当 Redis 瞬间不可用的情况,需要报警出来,然后线下处理。

先删除 Redis,再写 MySQL

这种方式,我还真没用过,直接忽略吧。

先删除 Redis,再写 MySQL,再删除 Redis

这种方式虽然可行,但是感觉好复杂 ,还要搞个消息队列去异步删除 Redis。

先写 MySQL,再删除 Redis

比较推荐这种方式 ,删除 Redis 如果失败,可以再多重试几次,否则报警出来;

这个方案,是实时性中最好的方案,在一些高并发场景中,推荐这种。

先写 MySQL,通过 Binlog,异步更新 Redis

对于异地容灾、数据汇总等,建议会用这种方式 ,比如 binlog + kafka,数据的一致性也可以达到秒级;

纯粹的高并发场景,不建议用这种方案,比如抢购、秒杀等。

个人结论:

实时一致性方案 :采用“先写 MySQL,再删除 Redis”的策略,这种情况虽然也会存在两者不一致,但是需要满足的条件有点苛刻,所以是满足实时性条件下,能尽量满足一致性的最优解。

最终一致性方案 :采用“先写 MySQL,通过 Binlog,异步更新 Redis”,可以通过 Binlog,结合消息队列异步更新 Redis,是最终一致性的最优解。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 架构
    +关注

    关注

    1

    文章

    537

    浏览量

    26643
  • MySQL
    +关注

    关注

    1

    文章

    930

    浏览量

    29740
  • Redis
    +关注

    关注

    0

    文章

    394

    浏览量

    12249
  • binlog
    +关注

    关注

    0

    文章

    7

    浏览量

    1422

原文标题:从美团挖来的架构师居然这么设计DB+缓存,真的长见识了!

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    京东缓存中间件架构缓存内核优化

    一、京东缓存中间件架构 1、背景 在当今高并发、分布式的系统架构中,缓存已成为提升应用性能、降低数据库负载的核心组件。随着业务规模的扩大与系统复杂度的增加,
    的头像 发表于 04-03 16:18 1804次阅读
    京东<b class='flag-5'>缓存</b>中间件<b class='flag-5'>架构</b>与<b class='flag-5'>缓存</b>内核优化

    为何AI数据中心的系统架构师首选Arm平台

    过去十多年,云基础设施通过“抽象化”实现扩展,借助标准化服务器、虚拟化资源及软件层,有效弥合了硬件层面的差异。这种模式之所以行之有效,是因为部分工作负载能够容忍一定程度的低效。然而,人工智能 (AI) 工作负载无法容忍低效,也因此暴露出了传统架构在供电、散热、算力密度、内存带宽及系统整体性能方面的短板。
    的头像 发表于 03-24 10:23 482次阅读

    Springboot+SpringData+SpringCloud微服务架构课程

      后端进阶必学:SpringCloud 微服务高可用落地实战 在互联网技术飞速迭代的今天,单体应用架构已逐渐难以承载亿级流量的重担。对于渴望突破瓶颈、迈向架构师行列的后端开发者而言,掌握微服务架构
    的头像 发表于 03-19 16:08 317次阅读

    高通Oryon架构之父宣布离职:曾一手定义移动芯片黄金时代

    电子发烧友综合报道 近日,全球半导体领域的传奇架构师、高通工程高级副总裁杰拉德·威廉姆斯三世(Gerard Williams III) 在领英上正式宣布辞去高通职务,他表示将“开启人生新篇章”,但未
    的头像 发表于 02-05 13:44 3348次阅读

    软通动力与居然之家深化战略合作

    1月19日,软通动力信息技术(集团)股份有限公司与居然智家新零售集团股份有限公司在北京居然大厦签署战略合作协议,共同宣告将双方合作全面升级至“战略合作2.0”新阶段。双方将整合各自优势资源,围绕数智化转型升级、全球化市场联合拓展、生态空间建设等领域展开深度合作,共同推动行
    的头像 发表于 01-21 16:17 519次阅读

    在TR组件优化与存算一体架构中构建技术话语权

    需要掌握HBM2e接口协议 类脑计算要求理解脉冲神经网络(SNN) 光子计算涉及硅基光电子集成技术 参与某国家级AI芯片项目的团队透露,核心研发人员均具备\"处理器架构师\"
    发表于 08-26 10:40

    缓存之美:万文详解 Caffeine 实现原理(上)

    文章将采用“总-分-总”的结构对配置固定大小元素驱逐策略的 Caffeine 缓存进行介绍,首先会讲解它的实现原理,在大家对它有一个概念之后再深入具体源码的细节之中,理解它的设计理念,从中能学习到
    的头像 发表于 08-05 14:49 801次阅读
    <b class='flag-5'>缓存</b>之美:万文详解 Caffeine 实现原理(上)

    Tenstorrent 首席架构师:未来 RISC-V 会是计算机的主流

    强,适合定制化需求等。在 7 月 17 日第五届(2025)RISC-V 中国峰会的主论坛上,Tenstorrent 首席架构师 Wei-Han Lien 表示,Tenstorrent 投入了大量人力
    发表于 07-17 11:26 1541次阅读

    harmony-utils之CacheUtil,缓存工具类

    harmony-utils之CacheUtil,缓存工具类
    的头像 发表于 07-04 16:36 588次阅读

    高性能缓存设计:如何解决缓存伪共享问题

    在多核高并发场景下, 缓存伪共享(False Sharing) 是导致性能骤降的“隐形杀手”。当不同线程频繁修改同一缓存行(Cache Line)中的独立变量时,CPU缓存一致性协议会强制同步整个
    的头像 发表于 07-01 15:01 877次阅读
    高性能<b class='flag-5'>缓存</b>设计:如何解决<b class='flag-5'>缓存</b>伪共享问题

    如何释放异构计算的潜能?Imagination与Baya Systems的系统架构实践启示

    报告作者:PallaviSharma,Imaginaiton产品管理总监Dr.EricNorige,BayaSystems首席软件架构师关注Imagination公众号,消息框发送【异构计算】,即可
    的头像 发表于 06-13 08:33 1366次阅读
    如何释放异构计算的潜能?Imagination与Baya Systems的系统<b class='flag-5'>架构</b>实践启示

    MCU缓存设计

    MCU 设计通过优化指令与数据的访问效率,显著提升系统性能并降低功耗,其核心架构与实现策略如下: 一、缓存类型与结构 指令缓存(I-Cache)与数据缓存(D-Cache)‌ I-Ca
    的头像 发表于 05-07 15:29 1266次阅读

    Nginx缓存配置详解

    Nginx 是一个功能强大的 Web 服务器和反向代理服务器,它可以用于实现静态内容的缓存缓存可以分为客户端缓存和服务端缓存
    的头像 发表于 05-07 14:03 1377次阅读
    Nginx<b class='flag-5'>缓存</b>配置详解

    带你参观一下射频工程的试验台

    台也是一个必备好像是keysight的仪器底噪怎么这么高?一个标准的测试站竟然需要这么多仪器居然还有格子?我好想要这个mini小暗室这是不是像极了你的实验桌?有没
    的头像 发表于 04-30 18:34 571次阅读
    带你参观一下射频工程<b class='flag-5'>师</b>的试验台

    AD8367 500 MHz 、45dB线性dB可变增益放大器技术手册

    AD8367是一款高性能可变增益放大器,设计用于在最高500 MHz的中频频率下工作。从外部施加0至1 V的模拟增益控制电压,可调整45 dB增益控制范围,以提供20 mV/dB输出。精确的线性dB
    的头像 发表于 04-22 09:52 2133次阅读
    AD8367 500 MHz 、45<b class='flag-5'>dB</b>线性<b class='flag-5'>dB</b>可变增益放大器技术手册