← 返回首页

缓存与数据库一致性如何取舍

一次旧数据问题之后,我重新梳理了缓存更新的顺序。

上周遇到一个挺别扭的问题:后台明明已经改了商品名称,用户端刷新几次,看到的还是旧名字。

我最初以为是浏览器缓存,查了一圈才发现,真正没更新的是服务端缓存。数据库里的值早就对了,只是删除缓存那一步碰巧失败,又没有留下明显日志。这个小问题折腾了半个下午,也提醒我重新想了一遍缓存和数据库到底该怎么相处。

我现在用的简单办法

读数据还是老套路:先读缓存,没有就查数据库,再把结果放回去。写数据时先更新数据库,成功后删除缓存。下一次读取自然会把新数据装回来。

我以前试过同时更新数据库和缓存,看起来省了一次回源,实际很容易在并发时把旧值覆盖回去。后来索性不耍聪明,删除比更新更省心。

当然,删除动作本身也会失败。现在我会记录失败任务并做有限重试,重要数据再通过变更消息补一次。听起来多了几步,但至少出了问题有地方查,不会只剩一句“用户说没更新”。

热点过期也会闹脾气

有一次批量导入缓存时,所有键都用了相同过期时间。第二天同一时刻,它们整整齐齐地失效,数据库负载立刻抬头。后来给过期时间加了一点随机偏移,曲线就安静多了。

不存在的数据我也会短暂缓存,挡住反复查询。不过时间设得很短,免得刚创建的数据还要在门外等太久。

最后还是那句朴素的话:数据库是账本,缓存只是便签。余额、库存和权限这些要紧事,不能只看便签。缓存方案不必显得高深,知道业务能忍受多久的旧数据,然后选最简单的做法,通常就够了。