实时同步缓存,与阶段性同步缓存——补充理解《补充》
根据 Redis 缓存的数据与 DBMS 中数据的同步性划分,缓存一般可划分为两类:实时同步缓存,与阶段性同步缓存。
实时同步缓存是指,DBMS 中数据更新后,Redis 缓存中的存放的相关数据会被立即清 除,以促使再有对该数据的访问请求到来时,必须先从 DBMS 中查询获取到最新数据,然后 再写入到 Redis。
阶段性同步缓存是指,Redis 缓存中的数据允许在一段时间内与 DBMS 中的数据不完全 一致。而这个时间段就是这个缓存数据的过期时间。
一、用 “外卖订单状态” 这个生活场景,通俗解释 实时同步缓存:
1. 初始状态(数据存储)
- DBMS(数据库):订单
ID=123
的状态是 “已接单”(这是最终数据,存在数据库里,不会丢)。 - Redis 缓存:也存着订单
123
的状态 “已接单”(方便外卖平台快速显示,不用每次查数据库,像手机里的 “缓存” 订单状态)。
2. 订单状态更新(DBMS 数据变化)
- 商家做了饭,点击 “配送中”(更新 DBMS 数据:订单状态从 “已接单”→“配送中”)。
- 这时候,Redis 缓存里的旧状态必须马上失效(就像手机 APP 里的订单状态缓存被 “清空”),否则用户刷新还会看到 “已接单”(脏数据)。
3. 用户刷新订单(访问数据)
- 第一次刷新:
- APP 先查 Redis 缓存(看有没有订单状态),发现缓存被清空了(缓存未命中)。
- 只好去 DBMS 数据库查,拿到最新状态 “配送中”,然后 把这个新状态存回 Redis 缓存(下次刷新就快了)。
- 第二次刷新:
- APP 直接从 Redis 缓存拿 “配送中”(缓存命中),秒级显示,不用等数据库查询。
4. 为啥要这么做?(实时同步的意义)
- 数据准:用户看到的订单状态和数据库里的 完全一致(商家改了,APP 马上显示新状态,不会延迟)。
- 速度快:第一次刷新后,缓存里有新状态,后续刷新不用查数据库,像 “已取餐”“已送达” 这些状态切换时,用户体验更流畅。
5.对比 “阶段性同步”(比如外卖店铺名称,几天才改一次)
- 假设店铺名称存在 Redis 缓存,设置 24 小时过期(阶段性同步)。
- 商家改了店名(DBMS 数据变了),但 Redis 缓存里的旧店名还能存 24 小时(用户可能看到旧店名,直到缓存过期)。
- 这种适合 变化少、对实时性要求低 的数据(店名几天改一次,用户暂时看旧的也没关系,换来缓存性能)。
6.总结(人话版)
- 实时同步缓存:数据库一变,缓存马上删,下次访问必须从数据库拿新数据,再存回缓存(保证数据 “即时准”,适合订单状态、库存这些秒变的数据)。
- 就像外卖 APP 里的订单状态:商家每动一步(接单、配送、完成),APP 马上更新(背后就是 DBMS 改了,Redis 缓存失效,重新存新状态),用户永远看最新的,还不卡。
二、中间搞这个缓存的作用?
用 超市收银台扫码 的例子,告诉你为啥非要在数据库(DBMS)和应用之间加一层 Redis 缓存,看完秒懂!
场景:超市收银台扫码查商品价格
假设你去超市买东西,收银员扫码查价格,背后有两种模式:
模式一:直接查数据库(无缓存)
- 流程:
扫码 → 系统直接访问 DBMS 数据库 → 查商品表 → 返回价格(比如 “可乐 3 元”)。 - 问题:
- 慢:如果同时有 100 个人排队结账,每个扫码都要查数据库,数据库像 “堵车的十字路口”,响应变慢,排队时间暴涨。
- 容易崩:数据库扛不住高并发查询(比如双 11 超市大促销),可能直接 “罢工”,整个收银系统瘫痪。
模式二:加 Redis 缓存(有缓存)
- 流程:
- 第一次扫码(比如 “可乐”):
- 系统先查 Redis 缓存 → 发现没数据(缓存未命中)。
- 再查 DBMS 数据库 → 拿到价格 “3 元”,同时把价格存到 Redis 缓存(比如存 1 小时)。
- 之后 1 小时内再扫可乐:
- 系统直接从 Redis 缓存取数据(缓存命中)→ 瞬间显示价格,不用查数据库。
- 第一次扫码(比如 “可乐”):
- 好处:
- 快如闪电:99% 的扫码请求直接走缓存,像从 “收银台抽屉” 里拿数据,比 “去仓库翻账本” 快 10 倍以上。
- 数据库减压:数据库只需要处理第一次查询,后续请求全被缓存 “拦截”,像给数据库雇了个 “前台接待”,减少 90% 的压力。
- 体验好:结账速度快,排队变短,顾客不抱怨,超市效率高。
缓存的核心作用总结(用大白话讲)
-
当 “快速访问” 比 “绝对实时” 更重要时,缓存就是救星
- 比如:商品价格、用户信息、首页推荐数据(这些数据偶尔几分钟不一致没关系,但必须让用户秒级看到)。
- 反例:银行转账金额(必须绝对实时,这时缓存可能闯祸,所以用实时同步策略,甚至不用缓存)。
-
给数据库 “减负”,防止它被压垮
- 数据库像 “慢条斯理的老会计”,适合处理少量、复杂的写操作(比如修改库存);
- 缓存像 “手脚麻利的临时工”,专门处理大量、简单的读操作(比如查价格),分工合作。
-
提升用户体验:让 APP / 系统 “不卡顿”
- 比如刷朋友圈、看新闻列表,数据先从缓存取,秒级刷新;后台再慢慢从数据库更新缓存,用户完全感知不到延迟。
回到之前的外卖例子:为啥订单状态要用实时同步缓存?
- 订单状态(已接单→配送中) 是 “实时性要求高 + 读多写少” 的数据:
- 写操作少:商家改状态是偶尔的(比如每天几百单)。
- 读操作多:用户、骑手、商家可能每秒都在刷新订单状态(比如 10 万人同时看)。
- 如果不用缓存:每次刷新都查数据库,数据库会被 “读爆”,页面加载慢,甚至崩溃。
- 用实时同步缓存:
- 写数据时(改状态),先更新数据库,再立即删缓存(保证缓存无旧数据)。
- 读数据时,第一次查数据库 + 存缓存,后续全走缓存,速度起飞,同时数据还是准的。
一句话总结:缓存是 “用空间换时间” 的魔法
- 牺牲一点内存空间(Redis 存在内存里),
- 换来 10 倍以上的读取速度,并让数据库 “轻松活到下班”。
- 就像超市在收银台抽屉里放常用商品价格表:查价快、不堵车,数据库(仓库账本)只需要处理罕见商品或价格变动。
现在明白为啥程序员总说 “先查缓存,再查数据库” 了吧?本质是为了 “快” 和 “稳”,缺一不可~
三、用 “朋友圈头像” 这个生活场景,通俗解释 阶段性同步缓存
用 “朋友圈头像” 这个生活场景,通俗解释 阶段性同步缓存,让你秒懂 “为什么允许数据暂时不一致” 和 “过期时间” 的作用:
场景:微信朋友圈查看好友头像
假设你刷朋友圈,看到好友小明的头像,背后的技术逻辑是这样的:
数据特点:
- 读多写少:小明可能一年改一次头像(写操作少),但你和其他 1000 个好友每天会看他头像 10 次(读操作极多)。
- 实时性要求低:即使小明刚改完头像,你过几分钟看到旧头像也没关系(不影响聊天,非关键数据)。
阶段性同步缓存的流程(带过期时间):
-
初始状态(第一次看头像):
- DBMS(数据库):存储小明的头像地址
img/123.jpg
(最新数据)。 - Redis 缓存:无数据(首次访问)。
- 流程:
- 你刷到小明的朋友圈 → 系统先查 Redis 缓存(未命中)→ 查数据库 → 拿到头像地址
img/123.jpg
→ 存入 Redis 缓存,并设置过期时间 30 分钟(SET user:123:avatar img/123.jpg EX 1800
)。
- 你刷到小明的朋友圈 → 系统先查 Redis 缓存(未命中)→ 查数据库 → 拿到头像地址
- DBMS(数据库):存储小明的头像地址
-
小明改头像了(DBMS 数据更新):
- 小明把头像换成
img/456.jpg
→ 系统 只更新数据库,不主动删除 Redis 缓存(这是关键!)。 - 此时 Redis 缓存中还是旧头像
img/123.jpg
(允许暂时不一致)。
- 小明把头像换成
-
你在 30 分钟内刷新朋友圈(缓存未过期):
- 系统查 Redis 缓存 → 拿到旧头像
img/123.jpg
→ 直接显示(无需访问数据库,速度极快)。 - 你看到的是旧头像,但小明的新头像已经存在数据库里了(数据不一致,但在允许的时间范围内)。
- 系统查 Redis 缓存 → 拿到旧头像
-
30 分钟后(缓存过期):
- 你再次刷新 → 系统查 Redis 缓存(发现过期 / 失效)→ 回源数据库 → 拿到新头像
img/456.jpg
→ 更新 Redis 缓存(下次刷新就显示新头像了)。
- 你再次刷新 → 系统查 Redis 缓存(发现过期 / 失效)→ 回源数据库 → 拿到新头像
核心逻辑:用 “时间换性能” 的权衡
-
为什么允许不一致?
- 如果每次改头像都强制删除缓存(实时同步),那么:
- 小明改一次头像,接下来 1000 个好友的每次访问都要查数据库(数据库压力大)。
- 而实际场景中,头像属于 “非敏感非实时数据”,晚几分钟看到新头像不影响用户体验。
- 阶段性同步的策略:设置合理的过期时间(如 30 分钟),在这段时间内用旧缓存响应请求,大幅减少数据库压力,同时最终(过期后)保证数据一致。
- 如果每次改头像都强制删除缓存(实时同步),那么:
-
过期时间(TTL)的作用:
- 相当于给缓存数据设置一个 “保质期”,确保旧数据不会永远存在。
- 时间设置原则:数据更新频率越低,过期时间可以越长(如静态页面设 1 天;半静态数据设 1 小时)。
适用场景举例(适合阶段性同步的典型数据)
场景 | 数据类型 | 过期时间设置 | 为什么用阶段性同步? |
---|---|---|---|
电商商品详情页 | 商品描述、规格参数 | 1 小时 - 1 天 | 商品信息很少修改,用户偶尔看到旧描述不影响购买。 |
新闻 APP 首页新闻列表 | 新闻标题、摘要 | 30 分钟 | 新闻更新有周期性,旧列表不影响用户浏览体验。 |
网站静态资源(CSS/JS) | 静态文件版本号 | 12 小时 | 静态文件几乎不变,浏览器和缓存共同加速访问。 |
社交平台用户粉丝数 | 用户粉丝数统计(非实时) | 5 分钟 | 粉丝数偶尔延迟显示,用户不敏感(非交易数据)。 |
对比实时同步缓存(一目了然)
维度 | 实时同步缓存 | 阶段性同步缓存 |
---|---|---|
数据一致性 | 强一致(DBMS 改后缓存立即失效) | 最终一致(过期时间内允许不一致) |
适用场景 | 交易数据(如订单金额、库存) | 非实时数据(如头像、商品描述) |
数据库压力 | 较高(每次写操作都可能触发查库) | 低(大部分读请求走缓存) |
典型过期时间 | 无(缓存随写操作立即更新) | 分钟级 - 天级(根据数据更新频率) |