第 5 章 · 缓存第 1 页,共 4 页
同一个答案,为什么不必每次都去数据库现查?
首页的「今日热门」人人都要看,每看一次都去数据库现查,同一个答案就被查了成千上万次。能不能查一次,存起来,让后来的人直接用?
为什么需要
晚饭前,百家菜(本课程虚构的菜谱网站)每秒要收到约 1,000 个读取请求(演示值),打开首页的最多。「今日热门」列出当天最热的 10 道菜,首页每打开一次,都要向现查一遍(第 3 章):同一个问题一秒里被问上几百遍,答案都一样。
这份列表很少变,却被读得极多,正是第 3 章说的。每个请求都这样现查,数据库的很快超过 100%,了。
办法是把查过的答案暂时放在更快、更近的地方,下次直接用,这叫(cache)。你平时在手机里清理的「缓存」,也是 App 这样存下的。这像把常用的文件放在办公桌上,不必每次去档案室调;只是档案室里的原件改了,桌上那份不会跟着改(第 2 页讲)。
怎样做
读取分三步,都由服务器来做:
- 第 1 步,先查缓存:服务器按答案的名字去问缓存,这个名字叫(cache key),例如「菜谱:1024」(第 1024 号菜谱);同一个问题总得算出同一个键,才找得到。缓存里有,叫(cache hit),直接拿来用。
- 第 2 步,没命中就查数据库:缓存里没有,叫(cache miss),下文简称没命中,服务器这才去数据库查。
- 第 3 步,放回缓存:服务器把查到的结果放进缓存,这叫(cache fill),下一位要同一份答案的读者就能命中。在本章这种做法里,缓存自己不会去数据库查。
下图把三步画成两条路线:命中的只走到缓存,没命中的从服务器直接去数据库。
命中率:还有多少请求要去数据库
先看这里先按「下一步」,看没有缓存时,这一秒的 1,000 个请求都去了哪里。
- 一个点代表一批请求,N 是这一批的个数
数据库框底部的条是这一秒的(到达的查询 ÷ 每秒能处理的 400 次):绿色有空,橙色七成以上,红色满了,满了以后另外写出这一秒查不完、要排队的个数。
还没开始。按「下一步」一步一步看这一秒里的 1,000 个请求,也可以直接看结果。
示意:查一次缓存约 1 毫秒;查一次数据库,不排队时约 10 毫秒,数据库每秒最多处理 400 次查询。数据库越忙,查一次要等得越久,这里按第 2 章那种最简单的排队模型推算;负载到了 100%,查不完的越排越长,算不出固定的等待。
在上图里换成「有缓存」,按「下一步」走完三步。这 1,000 个请求问的是许多份不同的答案;没命中的,是第一次被问到、过期了、因为数据改了被删掉或被清出去的(后两页讲)。所有查找中能在缓存里命中的比例,叫(hit rate)。到达数据库的请求 = 全部请求 ×(1 − 命中率):命中率 90% 时每秒 100 个,99% 时只有 10 个,只高 9 个百分点,数据库的活少了九成。再选 65%:平均等待从 80% 时的 5 毫秒涨到 29 毫秒,越接近满载,等待涨得越急(第 2 章)。调到 0%,到达数据库的和没有缓存时一样多,还白问了一次缓存,反而略差。
这样的缓存放在服务器和数据库之间,叫,通常是另外的一台或一组机器;也有的直接做进数据库软件里,例如打车软件 Uber 的数据库(2024)。
缓存快,是因为答案已经查好,放在里:连同来回的路,查一次约 1 (千分之一秒);数据库常要读、做计算,一次要几毫秒或更久。
手机上还有一层:第 1 章讲过的,请求先经过它,才到服务器。
两层缓存:请求在哪一层被拦下
先看这里先按「打开首页」,看你第一次打开首页时,请求走到了哪里。
- 命中:缓存里有这份答案
- 没命中:缓存里没有,要去数据库查
还没打开:手机和服务器旁的缓存里都还没有首页。按「打开首页」,看请求这一次走到哪里。
浏览器缓存只在这一部手机上,服务器旁的缓存为所有读者共用。图里只看首页这一份答案。
在上图里换成「另一位读者」,再按「打开首页」:他的手机里没有这一份,却在服务器旁的缓存里命中,因为你那一次已经放了回去。只帮一个人的缓存叫,例如浏览器缓存;帮所有人的叫。服务器旁的缓存人人共用,你收藏了哪些菜这类因人而异的内容就不能随便放进去,否则别人可能拿到你的。
代价是什么
缓存要多占机器、要人维护。更要紧的是依赖:第一张图里的数据库每秒最多处理 400 次查询(示意),离开缓存就接不住每秒 1,000 个读取请求。
资料来源
以下资料均于 2026-10-23 和 2026-10-26 访问。