缓存停了,压力全回到数据库
一、缓存停掉的那几分钟,用户看到什么
缓存就是先把查过的结果存一份,下次直接取。这一层服务一停,页面不会立刻全白,第一分钟还正常,浏览器和本机还留着一些旧页面。
第二分钟开始,首页的请求全部转到数据库。查询排起队,接口一个接一个超时。
用户看到的是转圈、报错、反复点击。客服接到的话是网站打不开了。
举个例子:一家卖生鲜的小店,首页的商品列表和商品详情都放在缓存里。促销开始前,缓存服务重启了一次,页面先是还能打开,随后接口一个接一个超时,下单的人停在支付页。
真正危险的不是这几分钟的报错,是数据库被压到起不来。缓存可以重启,数据库被拖垮,恢复要按小时算。
二、缓存平时替数据库挡了什么
用户打开一个页面,系统要查十几张表。每次都查库,数据库再强也扛不住。
缓存把查过的结果放在内存里,下一次同样的问题直接取。数据库只处理没查过的那部分。
所以缓存的作用不是让页面快一点,是让数据库只做它做得完的那部分。
假设一个站点的请求里,七八成落在同一批数据上:首页文章、分类列表、商品详情、站点配置。这批数据适合缓存。
这家小店的首页列表、商品详情和分类页,就属于适合缓存的那一批。
三、哪些数据能放进缓存
先看两件事:这份数据多久变一次,变了以后晚几分钟被看到能不能接受。
变化慢、晚一点看到也无所谓的,适合缓存。比如文章正文、分类名称、站点配置。
余额、库存、订单状态这类,晚一分钟看到就可能出错,不适合直接缓存,或者只能缓存很短时间。
还有一类不该缓存:每次请求都不同、跟着人走的数据。放进缓存既占内存,又容易把别人的数据给错人。
判断的办法很朴素:把这份数据贴到首页上,让所有人看同一份,会不会出事。会,就不要缓存。
这家小店的库存和价格只缓存很短时间,余额和订单状态不进缓存。
四、缓存里的数据旧了,用户会不会发现
管理员改了一篇文章,前台却还是旧标题。用户刷新几次都一样,就会来问。
这不是缓存坏了,是缓存不知道数据变了。缓存只认自己存的那一份;没人来通知,就一直是旧的。
解决办法有两种。一种是改完数据就把对应的缓存删掉,下一次请求重新查库。另一种是给缓存定一个最长存活时间,到点自动作废。
第一种快,但要在每个改数据的地方都记得删。漏一处,那一处就一直旧着。第二种慢一点,但不会漏。
小团队先做第二种,把最长存活时间定短一些。等改数据的地方稳定了,再补第一种。
五、过期时间怎么定
过期时间太短,缓存刚存下就失效,等于没缓存,数据库还是被反复查。
过期时间太长,数据变了前台半天不更新,用户看到的和后台不一致。
先从业务能接受的最大延迟倒推。文章晚十分钟更新能接受,就定十分钟。价格可以缓存,但时间要很短,改价时主动更新;一秒的旧价都不能接受的地方,就不要缓存价格。
同一批缓存不要设成同一个到期时间。全部在同一秒失效,请求会一起压到数据库。
在到期时间上加一点随机,比如十分钟上下浮动一分钟,压力就散开了。
六、热点数据挤在一条上怎么办
假设首页第一条文章或最热的那个商品,请求量是普通数据的几百倍。
这份数据过期的那一瞬间,所有请求同时发现缓存没了,一起回数据库查同一行。
数据库接住几百个相同的查询,很容易被这一下打满。
办法是只让一个请求去查,其他请求等这个请求的结果。查到之后放回缓存,后面的请求直接拿。
另一种办法是热点数据不设到期,后台改动时主动更新缓存。哪一种都要提前想到,不能等出事再补。
促销那天最热的一款水果,请求都挤在同一条数据上;他们让一个请求去查,其他请求等结果。
七、缓存和数据库,谁先动
改数据的时候,先改数据库还是先改缓存,结果不一样。
先改缓存再改数据库,中间出错,缓存里是新值,数据库里是旧值。下一次从数据库补回来,新值又被旧值盖掉。
先改数据库再删缓存,中间出错,数据库是新值,缓存里还是旧的。下一次请求会重新查库,拿到新值。
两种都有出错的可能,但后一种错得更轻:多数情况下,下一次请求会重新查库,拿到新值。并发读的时候,仍可能有人把旧值写回缓存。
所以顺序定成:先写数据库,再删缓存。删不掉的时候要记下来,不要当没发生。
八、缓存服务要不要多开一台
只有一台缓存,它重启或者机器出问题,所有请求同时回数据库。
多开一台,一台停了另一台还能接。但两台之间要同步数据,成本也跟着上来。
小团队先算一笔账:缓存停十分钟,数据库能不能接住。能接住,一台也够,先不做多台。
接不住,就要做。做的顺序是先做一台主、一台备,主出问题时由备机接替;再做容量分流。不要一上来就上集群。
缓存重启后是空的。先把热点数据预热一遍,或者分批放量,别让数据库一次接住全部请求。
这家店当时只有一台缓存;出事之后他们算过,停十分钟数据库接不住,于是加了一台备机。
九、缓存空了,数据库补得回来吗
缓存是可以丢的。丢了以后,请求回数据库重新查,再放回缓存。
前提是数据库能接住这些突然回来的请求。如果平时九成请求都被缓存挡住,缓存一空,数据库要接的就是平时的十倍。
所以缓存不是让数据库变小,是把平时承受的压力藏了起来。藏起来的那部分,在缓存出事时会一次还回来。
上线前做一次演练:把缓存清空,看数据库能不能撑住,多久恢复。这个数比任何监控图都实在。
他们后来做了一次清空缓存的演练,发现数据库撑不住,先把余量加上去了。
十、怎么提前知道缓存快撑不住
看三个数:缓存的内存用了多少、命中率是多少、数据库的查询量有没有异常上升。
内存接近上限时,缓存会开始淘汰旧数据。命中率跟着下降,数据库的查询量就会慢慢上来。
命中率突然掉,先看是不是有一批缓存同时到期,再看是不是有人清空过缓存。
这三个数要放在同一块面板上,值班的人一眼能看出是缓存的问题还是数据库的问题。
十一、小团队最少做哪几件
第一,列出哪些数据放进了缓存,各自的到期时间写清楚。
第二,给到期时间加随机,不要让一批同时失效。
第三,热点数据做一层保护,只让一个请求回数据库查。
第四,定好改数据的顺序:先写数据库,再删缓存。
第五,做一次清空缓存的演练,记下数据库撑不撑得住。
十二、先做哪一步最要紧
先把缓存清空一次,看数据库会不会倒。这一步不花钱,花的是半天时间。
数据库撑得住,后面的到期时间、热点保护可以慢慢补。
数据库撑不住,就先不要急着扩大缓存范围。先给数据库留出余量,再谈缓存。
缓存是替数据库挡事的。挡不住的那一天,这笔压力还是要回到数据库身上。
先做的还是清空一次看数据库;这家店就是在那次演练里发现余量不够的。
本文作者:Aryee 发布时间:2026-10-25 20:41
本文出处:ARYEE.cn 固定链接:https://www.aryee.cn/archives/cache-down-pressure-back-to-database.html
转载或引用请连这一行一起带走;文中的代码与结论按当时环境成立,组件升级后请以官方文档为准。