数据库和缓存一致性问题全解析:从原理到实战
今天咱们唠唠数据库和缓存为啥总闹矛盾:比如改了数据库后缓存没及时更新。咱会对比四种更新方法的优劣,再聊聊咋用过期时间、消息队列这些招儿,让数据最终保持一致。
一、为什么缓存和数据库会闹矛盾?
1.1 缓存加速的底层逻辑
就像超市收银台旁边会放常用商品(方便快速结账),数据库旁边也会放一层缓存(Redis)。Redis 用内存存储数据,读数据速度比数据库快 10 倍以上 —— 比如 MySQL 每秒只能处理几千次查询,而 Redis 能处理 10 万次以上。
1.2 一致性问题的核心矛盾
当数据库更新后,缓存里的旧数据没及时删掉就会出问题。比如:
- 数据库里商品价格从 100 元改成 90 元
- 这时候如果缓存没更新,用户查到的还是 100 元
- 就像超市改了价签,但收银台旁边的促销牌没换,顾客会搞错价格
根本原因:数据库和缓存是两个独立的系统,没法像打包票一样同时完成更新,中间会有几毫秒的 “时差”。
二、更新缓存的四种方案对比
方案 1:先改数据库,再改缓存
操作步骤:
- 改数据库里的数据
- 改缓存里的数据
问题场景:
就像两个人同时改价格:
- 小王先把数据库价格改成 90 元
- 小李后把数据库价格改成 80 元
- 但小李先更新了缓存,小王后更新缓存
- 结果缓存里是 90 元,数据库是 80 元,价格对不上
适用场景:只有当很少人改数据时才好用
方案 2:先改缓存,再改数据库
操作步骤:
- 改缓存里的数据
- 改数据库里的数据
问题场景:
如果改数据库失败(比如网络断了),缓存里的新数据就成了 “假数据”。就像你先在促销牌上写了 90 元,结果仓库里没改价格,顾客结账时发现还是 100 元,会吵架。
方案 3:先删缓存,再改数据库
操作步骤:
- 删掉缓存里的数据
- 改数据库里的数据
问题场景:
比如你刚删掉促销牌,这时候有人来查价格:
- 他发现促销牌没了,就去仓库查旧价格 100 元
- 等他把旧价格写回促销牌后,你才把仓库价格改成 90 元
- 结果促销牌还是 100 元,和仓库对不上
改进方法:删两次缓存(等一会儿再删一次),但等多久很难把握
方案 4:先改数据库,再删缓存(推荐方案)
操作步骤:
- 改数据库里的数据
- 删掉缓存里的数据
优势:
- 只有删缓存前的几毫秒内,用户可能查到旧数据(比如你改完仓库价格,还没撕掉促销牌的几秒钟)
- 下一次用户查询时,发现缓存没数据,会自动从数据库取最新数据
推荐场景:大部分情况下都好用,尤其是买东西的人多、改价格的人少的场景
三、保证数据最终一致的三个大招
1. 给缓存设过期时间(必做)
就像牛奶有保质期,缓存也该设一个 “过期时间”。比如:
- 商品详情页缓存 300 秒
- 超过时间自动失效,下次查询时会从数据库取最新数据
- 就算更新缓存失败,最多 300 秒后数据也会变正确
2. 用消息队列 “补刀”(进阶方法)
如果删缓存失败(比如 Redis 突然断网),可以用消息队列来补救:
- 改完数据库后,发一条 “删缓存” 的消息到队列里
- 系统会反复尝试删缓存,直到成功为止
- 就像你给朋友发微信没成功,微信会一直重试直到发出去
3. 监听数据库变化(高级方法)
有一种工具能 “偷看” 数据库的修改记录(比如 Canal),只要数据库一更新,就自动触发删缓存操作:
- 不需要在代码里到处写删缓存的逻辑
- 不管哪个系统改了数据库,都能统一处理
- 就像超市装了监控,只要仓库改价格,收银台旁边的促销牌自动更新
四、复杂场景的应对技巧
场景 1:改一个数据要删多个缓存
比如用户修改了个人信息,需要同时更新:
- 个人主页缓存
- 粉丝列表缓存
- 积分排名缓存
解决方案:发一条消息,里面写上所有要删的缓存名称,让专门的系统统一处理,避免代码里到处都是删缓存的代码。
场景 2:大量用户同时查一个热门商品(缓存击穿)
比如双 11 时, tens of thousands of people 同时查某款手机的价格,可能导致缓存失效后数据库被挤爆。
解决方案:加一把 “锁”:
- 第一个查的人去数据库取数据,其他人等 50 毫秒
- 避免所有人同时挤向数据库
- 就像超市结账时,只让一个人先去仓库拿货,其他人在门口排队
五、核心结论
- 没有完美方案就像做饭时很难同时做到 “快” 和 “好吃”,缓存和数据库也无法完全一致,只能尽量缩短不一致的时间。
- 策略选择原则
- 如果查数据的人多、改数据的人少:用 “先改数据库,再删缓存”
- 如果改数据的人多:可以直接查数据库,少用缓存
- 工程实践关键
- 所有缓存必须设过期时间(比如 10 分钟)
- 重要数据更新时,用消息队列确保缓存一定被删掉
结语:技术的本质是权衡
就像开车时要在速度和安全之间找平衡,开发系统时也要在 “数据一致性” 和 “系统性能” 之间做选择。通过本文的方法,既能让系统跑得飞快,又能把数据不一致的概率降到极低 —— 这就是分布式系统的魅力所在。
评论
发表评论
|
|