高并发系统设计 40 问
唐扬
美图公司技术专家
49013 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
高并发系统设计 40 问
15
15
1.0x
00:00/00:00
登录|注册

13 | 缓存的使用姿势(一):如何选择缓存的读写策略?

如果是“脏”的则将数据写入后端存储中并加载数据到缓存块儿,否则由缓存组件将后端存储中的数据加载到缓存中
缓存不命中则寻找可用的缓存块儿
缓存命中则直接返回数据
不存在则从数据库中同步加载数据
查询缓存中数据是否存在
"Write Miss"方式:Write Allocate vs. No-write allocate
更新缓存中的数据并同步更新到数据库中
查询要写入的数据在缓存中是否已经存在
影响缓存命中率的解决方案
解决方法:不更新缓存,而是删除缓存中的数据,在读取数据时再从数据库中读取数据更新到缓存中
并发更新导致数据不一致
删除缓存记录
更新数据库中的记录
将数据写入缓存并返回给用户
缓存不命中则从数据库中查询数据
缓存命中则直接返回数据
从缓存中读取数据
读的策略
"Write Miss"时采用的是“Write Allocate”的方式
写入数据时只写入缓存并标记为“脏”,脏块儿只有再次使用时才会写入后端存储中
Read Through策略
Write Through策略
问题与解决
写策略
读策略
思考在日常工作中使用了哪些缓存的读写策略
Write Back策略是计算机体系结构中的策略,异步写入后端存储的策略有很多应用场景
Read/Write Through和Write Back策略需要缓存组件的支持,适合在实现本地缓存组件时使用
Cache Aside是在使用分布式缓存时最常用的策略
Write Back(写回)策略
Read/Write Through(读穿/写穿)策略
Cache Aside(旁路缓存)策略
一课一思
课程小结
缓存的读写策略
使用缓存的正确姿势
缓存的定义、分类以及不足
缓存的使用姿势

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

上节课,我带你了解了缓存的定义、分类以及不足,你现在应该对缓存有了初步的认知。从今天开始,我将带你了解一下使用缓存的正确姿势,比如缓存的读写策略是什么样的,如何做到缓存的高可用以及如何应对缓存穿透。通过了解这些内容,你会对缓存的使用有深刻的认识,这样在实际工作中就可以在缓存使用上游刃有余了。
今天,我们先讲讲缓存的读写策略。你可能觉得缓存的读写很简单,只需要优先读缓存,缓存不命中就从数据库查询,查询到了就回种缓存。实际上,针对不同的业务场景,缓存的读写策略也是不同的。
而我们在选择策略时也需要考虑诸多的因素,比如说,缓存中是否有可能被写入脏数据,策略的读写性能如何,是否存在缓存命中率下降的情况等等。接下来,我就以标准的“缓存 + 数据库”的场景为例,带你剖析经典的缓存读写策略以及它们适用的场景。这样一来,你就可以在日常的工作中根据不同的场景选择不同的读写策略。

Cache Aside(旁路缓存)策略

我们来考虑一种最简单的业务场景,比方说在你的电商系统中有一个用户表,表中只有 ID 和年龄两个字段,缓存中我们以 ID 为 Key 存储用户的年龄信息。那么当我们要把 ID 为 1 的用户的年龄从 19 变更为 20,要如何做呢?
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了缓存的读写策略选择的重要性,以及针对不同业务场景的不同策略。其中,介绍了Cache Aside(旁路缓存)策略,该策略以数据库数据为准,缓存数据按需加载,包括读策略和写策略。此外,还讨论了该策略可能出现的问题以及解决方案。文章还提到了在写入频繁时对缓存命中率的影响以及两种解决方案。最后,指出了除了Cache Aside策略外,还有其他几种经典的缓存策略,它们也有各自适用的使用场景。文章内容深入浅出,适合读者快速了解缓存读写策略的选择和应用。 在本文中,作者详细介绍了Read/Write Through(读穿/写穿)策略和Write Back(写回)策略,分别阐述了它们的核心原则和适用场景。Read/Write Through策略要求用户只与缓存打交道,由缓存和数据库通信,写入或读取数据,适合实现本地缓存组件。而Write Back策略则是在写入数据时只写入缓存,并在再次使用时才将数据写入后端存储,适用于计算机体系结构中的设计。此外,文章还提到了在实际开发过程中需要结合实际的业务特点灵活使用甚至加以改造,并鼓励读者结合实际工作中的情况进行讨论。 总的来说,本文通过深入的技术讲解,帮助读者了解了缓存的读写策略选择的重要性以及不同策略的适用场景,为读者提供了在实际工作中应用缓存策略的思路和方法。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《高并发系统设计 40 问》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(81)

  • 最新
  • 精选
  • 小可
    置顶
    工作中老师说的这几种缓存策略基本都用到了,特别是统计接口响应时间那个例子和我们的场景一样。管理平台统计一百多个节点的上报到队列中的数据,原来是按消费一批统计完直接批量入库,数据量太大(每秒两三千),压力全在数据库,系统也比较卡,并且如果入库不及时就会数据积压,后续都跟不上。现在是消费统计和入库分开,消费统计先放缓存,每分钟再将缓存同步到数据库,同步成功再提交消费offset,目前看还算稳定。

    作者回复: 👍

    2019-10-16
    9
    38
  • 任鹏斌
    读到这里突然想到一个开源项目https://github.com/apache/ignite,内存数据库,结合了关系型数据库和缓存的优点,如果只当缓存使用的话,可以自动加载和写入关系型数据库中的数据。完美解决一致性问题。但是好像国内使用的人不多。

    作者回复: 好滴,我关注一下~

    2019-10-16
    7
    52
  • 岁寒
    缓存一定会引入不一致的。。

    作者回复: 是的 所以解决的办法需要权衡一致性和性能

    2019-10-16
    32
  • 无形
    文中提到的第一个第一个缓存和数据不一致的问题,我认为这个问题的原因是,多个客户端更新缓存和数据库之间是无序的、并发的操作,这样必然导致数据不一致的问题,因此我们采用了监听binlog的方式,把Binlog扔到消息队列中,由一个leader来消费,负责更新缓存,保证了写缓存操作之间的顺序性,保证了缓存的准确性,避免了频繁读库。

    作者回复: 这样确实是一个比较好的方式,只是会稍微复杂

    2019-11-04
    15
    21
  • 长期规划
    老师,我理解WriteBack策略相当于缓存和缓冲区合二为一了,对吧。据我所知,MySQL的buffer pool使用了WriteBack策略,但为了防止系统崩溃后数据丢失,MySQL使用了WAL(Write-Ahead Logging)机制,写先日志。好像WAL在HBase等系统也在用

    作者回复: 是的

    2019-10-24
    16
  • yc
    write back策略读请求时“如果缓存不是脏的,则由缓存组件将后端存储中的数据加载到缓存中”,是不是写错了,如果缓存不是脏的,直接从缓存返回即可,为什么还要从后端记载数据到缓存然后返回?我看留言很多人都有同样的疑问,请老师解释一下,谢谢。

    作者回复: write back策略其实不算数据库和mc之间的策略,而是计算机体系结构中的策略,比如磁盘文件的缓存。它的完整读策略是这样的:如果缓存命中,则直接返回;如果缓存不命中,则重新找一个缓存块儿,如果这个缓存块儿是脏的,那么写入后端存储,并且把后端存储中的数据加载到缓存中;如果不是脏的,那么就把后端存储中的数据加载到缓存,然后标记缓存非脏。 是我的讲述不太清晰,感谢你的提问

    2019-10-17
    2
    14
  • 约书亚
    Cache Aside对缓存命中率两种解决方案中的1,可能是我没看懂,感觉没解决问题啊? 这里说在“更新数据时也更新缓存”,我理解就是先更新DB再更新缓存,这样除非在更新DB之前加分布式锁,否则在更新DB之后加分布式锁,再更新缓存,依然较高可能出现不一致的情况。 实际中我们确实用在更新缓存时用分布式锁或本地锁,只不过是发现缓存为空而去读DB时,为了解决穿透问题。 纯个人见解,除了cache aside,另外两种更贴近底层系统开发而不是商业应用开发。因为我们大多数人做的系统,都是低速存储都是数据库,是有复杂的业务逻辑约束的,比如唯一性等,不是那种简单的page/cpu cahce。我们经常的写操作一般都要借助数据库来检验这些约束并且在出错之后返回给用户。而如果直接与缓存打交道,且不论有些缓存的实现并不保证数据可靠性,也不能依靠缓存检验这些约束。 其实现在很多系统用的一种缓存模式是类似CQRS,写直接修改DB,异步更新到缓存,读只从缓存读数据。适合对数据不一致窗口可以容忍的场景。

    作者回复: 1. 是在更新数据库前加锁,锁的粒度是大了一些 2. 确实是更偏重底层开发

    2019-10-16
    3
    13
  • 程序水果宝
    使用写回策略,如果在缓存更新到数据库之前设备掉电了,那这样数据岂不是丢失了,请问这是怎么解决的呢,通过主备机制吗,缓存数据写两份?

    作者回复: 是有这个问题,比如pagecache在机器掉电之后就都是数据了。一个办法是将写入缓存的操作写入log里,类似lsm树的write ahead log

    2019-10-22
    2
    7
  • fdconan
    Cache Aside(旁路缓存)策略,对于读多写少场景,当一个写操作更新db后同时删除缓存。然后多个读就会回源,这不会造成db压力么?

    作者回复: 会的,这就是狗桩效应嘛~

    2019-10-23
    6
  • 七号叽
    老师你好,请问一下write back策略为什么读请求时是“如果缓存不是脏的,则由缓存组件将后端存储中的数据加载到缓存中”,而不是直接返回?谢谢

    作者回复: 否则缓存块就可能永远是脏的了

    2019-10-16
    10
    6
收起评论
显示
设置
留言
81
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部