缓存分层采用l1本地缓存(如caffeine)、l2 redis、l3 sql数据库三级结构,读写遵循cache aside策略实现最终一致,复杂查询、高实时性及强一致性场景应直查数据库。

SQL 和 Redis 结合做缓存分层,核心是让热数据走 Redis 快速响应,冷数据或复杂查询仍由 SQL 数据库兜底,既保性能又保一致性。
缓存分层怎么分:读场景的三级结构
常见分层不是“SQL + Redis”二选一,而是按访问频率和更新特性动态分流:
- 第一层(L1):本地缓存(如 Caffeine)——适合极热、只读、生命周期短的数据,比如接口开关、配置白名单;不跨进程,无网络开销,但不共享、需注意失效同步
- 第二层(L2):Redis 缓存——作为分布式共享缓存,承载用户会话、商品详情、订单状态等中高频读写数据;用 string、hash、zset 等结构匹配业务模型,加过期时间 + 主动刷新机制防雪崩
- 第三层(L3):SQL 数据库(MySQL/PostgreSQL)——最终数据源,负责事务、关联查询、范围扫描、唯一约束等 Redis 不擅长的操作;所有写操作必须先落库,再清理或更新 Redis
缓存与数据库怎么保持一致
强一致难做到,目标是“最终一致 + 可控延迟”。关键不在技术多炫,而在策略清晰:
DESTOON B2B网站管理系统是一套完善的B2B(电子商务)行业门户解决方案。系统基于PHP+MySQL开发,采用B/S架构,模板与程序分离,源码开放。模型化的开发思路,可扩展或删除任何功能;创新的缓存技术与数据库设计,可负载千万级别数据容量及访问。
- 写操作采用“先更新数据库,再删缓存”(Cache Aside)——避免并发写导致脏数据;删除而非更新缓存,防止中间态错误;配合延迟双删(删-写DB-休眠几百毫秒-再删)应对主从延迟
- 读操作“先查 Redis,未命中再查 DB 并回填”——注意空值缓存(如 setex key 60 “null”)防穿透;对频繁空查的 key 加布隆过滤器前置拦截
- 给缓存加逻辑过期时间(非 Redis TTL)——value 中嵌入时间戳,读取时判断是否过期,过期则异步刷新,不影响当前请求返回旧值,提升可用性
哪些 SQL 场景不适合放 Redis
不是所有数据库查询都该被缓存。盲目迁移反而增加复杂度和不一致风险:
- 实时性要求极高且变更频繁的数据——例如秒杀库存、聊天消息未读数,用 Redis 做计数器更合适,但需结合 Lua 脚本保证原子性,而不是缓存 SQL 查询结果
- 多表 JOIN、GROUP BY、ORDER BY LIMIT 复杂查询——Redis 不支持,硬塞 hash 或 list 模拟成本高、维护难;这类应优化 SQL + 索引,或用物化视图/ES 分担
- 权限类、审计类低频写高一致性要求的数据——如用户角色权限关系,更新少但错不得,直接查库更稳妥,缓存反而引入额外失效漏点
上线前必须验证的三件事
缓存加得快,问题暴露得更快。上线前重点看:
- 缓存命中率是否真实提升——别只看 Redis info stats 的 hit_rate,要结合业务维度(如某商品详情页缓存命中率 >95%),用监控打点比对 DB QPS 下降比例
- 写操作后缓存是否及时失效——模拟用户修改资料,检查 Redis 中对应 key 是否消失(或更新),并验证下次读是否触发回源且结果正确
- 大 Key、热 Key 是否有预案——用 redis-cli --bigkeys 扫描;对热 key 加本地缓存或改用 hash 分片;禁用 keys *,改用 scan 防阻塞
不复杂但容易忽略。分层不是堆技术,而是按数据特征和业务 SLA 划边界、定策略、配监控。









