第 5 章 · 缓存第 4 页,共 4 页
一条热门内容的缓存突然过期,会发生什么?
一道菜突然走红,每秒有几百位读者打开它,平时都在缓存里命中。可它的那一份总有过期的一刻,那时会发生什么?
为什么需要
酸汤肥牛突然走红,每秒约有 500 位读者打开它(演示值)。同一时间被特别多的请求访问的某一条数据,叫(hot key)。平时它一直在缓存里命中,数据库很清闲。
可它的那一份总有过期的一刻(第 2 页)。从没命中到服务器重新查出、放回新的一份,要花一些时间:这道菜的页面要拼好几张表(第 3 章),还要数出收藏它的人数,比第 1 页那种约 10 毫秒的查询慢得多,图里按约 1 秒算(示意)。这段时间里来的请求全都没命中,一起去数据库查同一道菜:每秒 500 个 × 1 秒,就是 500 个。这叫(cache stampede)。你平时说的击穿是被打穿;这里比喻挡在数据库前的缓存,对这道菜破了个洞,请求一拥而上。只是缓存并没有坏,新的一份放回去,洞就补上了。这个叫法没有统一的定义,本课程只指这种情形。
大量请求或程序在同一时刻涌向同一个地方,统称(thundering herd),字面意思是受惊后一齐狂奔的兽群,只是请求并没有受惊。缓存击穿是其中由到期引起的那一种。Facebook 2013 年的论文里,热门数据被频繁修改,缓存里的那一份一放回就失效,也就是因为数据又改了而被删掉,不是到期(第 2 页),许多读取只好去查数据库:这是由失效引起的惊群效应,不算缓存击穿。
怎样做
缓解的办法之一是(request coalescing):相同的请求同时到来时,只让第一个去查,其余的等它带回结果。服务器替正在查的键记一笔:第一个请求记上「我去查」,后来的看到有人在查,就在旁边等;查回来以后放回缓存一次,大家拿到同一个答案。
下图是酸汤肥牛的那一份过期前后。
一拥而上:酸汤肥牛的那一份过期以后
先看这里先按「下一步」,看过期以前的一秒里,500 个请求在哪里拿到答案。
- 命中:缓存里有这份答案
- 没命中:缓存里没有,要去数据库查
- 一个点代表一批请求,N 是这一批的个数
数据库框底部的条是图上这一秒的(到达的查询 ÷ 每秒能处理的 400 次):绿色有空,橙色七成以上,红色满了,满了以后旁边写出这一秒查不完、要排队的个数。
还没开始。按「下一步」,一步一步往下看。
示意:酸汤肥牛每秒被打开 500 次;涌向数据库的请求 = 每秒 500 个 × 重新查出、放回缓存要的时间,这段时间可以在上面换。数据库每秒最多处理 400 次查询,与第 1 页相同。这里假设每次查询占用的数据库处理能力一样多;真实的情况里,这道菜的查询要拼几张表,占用得更多,数据库会更早满,结论不变。图里只画一台服务器;真实的百家菜有好几台,每台各合并各的。
在上图里换一换重新查出要的时间:10 毫秒只有 5 个请求涌向数据库,1 秒就有 500 个,查得越慢,涌上来的越多。再打开请求合并:数据库只收到 1 次查询,其余的请求在服务器旁等它的结果。聊天软件 Discord 也这样做:许多用户同时读同一条数据时,它只查一次数据库(2023)。
别的办法还有:快过期时就让一个请求提前去重新查;或者过期以后先把旧的那一份发出去,同时在后台重新查。后台,指在一旁另做、读者不必等的事(第 7 章细讲)。第 2 页说过,旧答案算不算错要看内容;这里可以先给旧的,是因为过期只是时间到了,不代表内容改了。就算真改了,旧的通常也只多留到重新查好,最长不超过事先定好的期限。
代价是什么
合并也有代价:等着的请求要等第一个回来,第一个慢,大家一起慢;它失败了,等着的也拿不到结果。合并也只发生在同一处:请求分散在几台服务器上时,每台各合并各的,所以数据库会收到每台各一次查询。
合并以后一齐返回,还可能在下一处一拥而上。设计软件 Canva 2024 年的一次故障里,许多用户的设备都要下载新版网页编辑器的同一个文件,替它分发文件的内容分发网络(第 6 章讲)把这些请求合并成一次去取。网络出了问题,这一次取了约 20 分钟,等着的请求攒到 27 万多个。文件一到,它们同时完成,各台设备上的编辑器接着加载,又一齐向 Canva 的服务器发出请求,每秒的请求数冲到平时高峰的约 3 倍;再加上这些服务器自身的一个性能问题,一下子接不住了。
回顾:缓存这一章
- 先查缓存:服务器按缓存键问缓存,命中就用,没命中就查数据库、再放回缓存;到达数据库的请求 = 全部请求 ×(1 − 命中率)(第 1 页)。
- 旧答案:只等到期,旧答案最长留一个过期时间;修改时主动失效更快,但要先改数据库再删缓存,并留着过期时间兜底(第 2 页)。
- 放满了:按规则清出去一道,例如最久没用的先清出去;清出去的只是拷贝(第 3 页)。
- 一拥而上:热门内容的那一份一过期,重新查出以前来的请求都没命中、一起去查,查得越慢,涌上来的越多;只让一个去查,其余等它的结果(第 4 页)。
清理手机里的「缓存」以后,有的 App 下次打开可能会慢一些:先前存下的拷贝没了,只好重新去取,这正是第 3 页的。
资料来源
以下资料均于 2026-10-23 和 2026-10-26 访问。
- Optimal Probabilistic Cache Stampede Prevention
- Scaling Memcache at Facebook
- RFC 9111: HTTP Caching
- How Discord Stores Trillions of Messages
- RFC 5861: HTTP Cache-Control Extensions for Stale Content
- Caching challenges and strategies
- Canva incident report: API Gateway outage
- How Uber Serves Over 40 Million Reads Per Second from Online Storage Using an Integrated Cache
- How Uber Serves over 150 Million Reads per Second from Integrated Cache with Stronger Consistency Guarantees
- Free up storage on your Android device