在电商系统的缓存架构中,Redis 作为核心中间件,其内存容量的有限性与缓存数据的海量性始终存在矛盾。当缓存数据达到 Redis 内存上限时,若采用固定淘汰策略,易引发核心数据被误删、缓存命中率骤降等问题。ZKMall 开源商城早期使用单一的 “最近最少使用(LRU)” 淘汰策略,曾在促销活动中出现热门商品缓存被低频历史订单缓存挤出的情况,导致商品详情页查询响应时间从 50ms 飙升至 800ms,数据库 CPU 使用率突破 90%。为解决这一痛点,ZKMall 基于业务场景差异,构建 Redis 淘汰策略动态调整体系,最终实现缓存命中率提升至 98%、核心接口响应时间稳定在 60ms 内、数据库压力降低 75% 的显著成效。本文从业务适配、动态机制、实践效果三方面,拆解该方案的落地逻辑。
一、Redis 淘汰策略的核心价值与场景适配
Redis 淘汰策略的本质是在有限内存中筛选 “高价值” 缓存数据,其核心价值在于平衡缓存有效性与资源占用。Redis 提供 8 种淘汰策略,ZKMall 结合电商业务特性,筛选出 5 种核心策略,并针对不同缓存类型实现精准适配。
1. 商品类缓存:高频数据优先留存
商品类缓存是 ZKMall 访问量最高的缓存类型,涵盖基础信息(ID、名称、价格)、详情内容(规格、图片链接)、分类列表等数据,具有 “访问频率差异大、部分无明确过期时间” 的特点。
- 基础商品信息缓存(如goods:info:10086):无过期时间,采用 “allkeys-lru” 策略。热门商品日均访问量可达 10 万次,冷门商品仅 10 次左右,通过 LRU 淘汰近 30 天无访问的冷门商品缓存,可在有限内存中存储更多高频数据,商品详情页查询命中率稳定在 98% 以上。
- 促销商品缓存(如goods:promo:618:10086):设置活动结束后 1 小时过期,采用 “volatile-ttl” 策略。优先淘汰剩余时间短的非核心促销商品缓存(如活动尾声商品),保留核心主推商品缓存,避免促销期间缓存穿透。
- 商品分类列表缓存(如goods:category:3:list):访问频率中等且无过期时间,采用 “allkeys-lru” 策略。内存不足时,淘汰最近最少访问的小众分类列表,保障 “电子产品”“服装” 等热门分类的查询效率。
2. 订单类缓存:近期数据优先保障
订单类缓存包含快照(下单时商品信息)、状态(待付款 / 已发货)、用户订单列表,其访问频率随时间递减,历史数据价值低。
- 近期订单缓存(3 个月内,如order:snapshot:500123):设置 3 个月后过期,采用 “volatile-lru” 策略。用户查询近期订单的频率高(“我的订单” 页面日均访问 50 万次),优先保留最近访问的订单缓存,即使淘汰数据穿透至数据库,也因历史订单分表设计,查询压力可控。
- 历史订单缓存(3 个月前,如order:snapshot:400987):设置 7 天过期,采用 “volatile-ttl” 策略。历史订单日均访问不足 1 万次,优先淘汰即将过期的数据,释放内存用于存储高价值缓存。
- 订单状态缓存(如order:status:500123):无过期时间,采用 “allkeys-lru” 策略。订单创建 24 小时内访问频率最高,之后骤降,通过 LRU 淘汰低频状态缓存,避免内存占用过高。
3. 用户类缓存:核心会话不可丢失
用户类缓存涵盖会话(Token、登录状态)、基础信息(昵称、头像)、地址列表,与用户体验强相关,部分数据不可丢失。
- 用户会话缓存(如user:session:token123):2 小时过期,采用 “volatile-lru” 策略。优先保留最近活跃用户的会话缓存,长时间未操作(2 小时内无交互)的会话可淘汰,用户重新登录即可恢复,对体验影响小。
- 用户基础信息缓存(如user:info:7890):无过期时间,采用 “allkeys-lru” 策略。用户基础信息访问频率高(打开个人中心必查)且数据体积小(单条约 1KB),淘汰半年内无访问的沉睡用户信息,释放内存同时保障活跃用户数据安全。
- 用户地址列表缓存(如user:address:7890):30 天过期,采用 “volatile-ttl” 策略。地址列表访问频率低于会话与基础信息,且用户更新地址后旧数据价值降低,优先淘汰即将过期的地址缓存。
4. 临时类缓存:低价值数据快速清理
临时类缓存包括活动倒计时、未登录用户购物车、验证码,生命周期短、过期后无价值。
- 活动倒计时缓存(如activity:countdown:618):活动结束后过期,采用 “volatile-ttl” 策略。活动期间每秒访问 1 万次,优先保留缓存;活动结束后因 TTL 到期自动淘汰,无需人工干预。
- 未登录用户购物车缓存(如cart:temp:device456):7 天过期,采用 “volatile-random” 策略。未登录用户购物车数据价值低(登录后可能合并 / 丢弃),且访问频率差异小,随机淘汰性能开销低,优于 LRU。
- 验证码缓存(如verify:code:phone138):5 分钟过期,采用 “volatile-ttl” 策略。验证码生命周期极短,优先淘汰剩余时间最短的数据,最大程度减少内存占用。
二、淘汰策略的动态调整机制
固定淘汰策略无法应对 ZKMall 业务的动态变化(如促销流量激增、时段访问差异),需构建 “业务周期预调整 + 实时监控触发 + 键前缀精细化” 的动态体系。
1. 基于业务周期的预调整
ZKMall 业务存在明显周期性(促销活动、周末高峰、每日峰值时段),需提前调整策略优化资源分配。
- 促销预热期(如 618 前 1 周):商品类缓存访问量预计增长 3 倍,订单类增长 2 倍。将商品基础信息缓存的 “allkeys-lru” 策略配合增大maxmemory阈值,同时将订单类 “volatile-lru” 切换为 “volatile-ttl”,淘汰即将过期的历史订单缓存,为促销商品缓存预留内存。
- 促销高峰期(如 618 当天):热门商品缓存访问频率骤增,将其过期时间从 24 小时延长至 72 小时,淘汰策略临时调整为 “noeviction”(仅针对热门商品键前缀),避免 LRU 误删导致缓存穿透。
- 促销回落期(如 618 后 3 天):订单查询量激增,商品访问量回落。将订单类策略从 “volatile-ttl” 切回 “volatile-lru”,优先保留近期订单缓存;商品类恢复常规 “allkeys-lru”,淘汰冷门商品缓存。
2. 基于实时监控的动态触发
ZKMall 通过 Prometheus+Grafana 监控 Redis 核心指标,指标触发阈值时自动调整策略。
- 缓存命中率监控:为不同缓存设置阈值(商品类≥98%、订单类≥95%、用户类≥97%)。当商品类命中率连续 5 分钟低于 98%,自动将 “allkeys-lru” 切换为 “volatile-lru”(若部分商品缓存有过期时间),同时触发告警排查热门商品缓存淘汰情况。
- 内存使用率监控:设置 85% 预警线、90% 调整线。内存使用率连续 3 分钟超 90% 时,若当前为 “volatile-lru”,自动切换为 “allkeys-lru” 扩大淘汰范围;若已为 “allkeys-lru”,触发缓存预热(低频缓存迁移至磁盘)并推送扩容建议。
- 键过期率监控:监控过期键占比,订单类缓存过期率连续 10 分钟超 50% 时,自动将 “volatile-ttl” 切换为 “volatile-lru”,优先保留近期访问订单缓存,避免集中过期引发缓存雪崩。
3. 基于键前缀的精细化控制
ZKMall 缓存键采用 “业务模块 + 类型 + 唯一标识” 命名(如goods:info:10086),支持按键前缀设置差异化策略。
- 前缀策略配置:通过 Redisconfig set命令,为goods:info:设 “allkeys-lru”、order:snapshot:设 “volatile-lru”、verify:code:设 “volatile-ttl”,避免 “一刀切” 策略误删核心数据。
- 异常场景切换:用户会话缓存命中率下降时,仅将user:session:前缀策略从 “volatile-lru” 临时切为 “noeviction”,不影响其他缓存,减少整体体系波动。
- 策略优先级定义:设置 “noeviction”>“volatile-lru”>“allkeys-lru” 优先级,内存不足时优先执行高优先级策略。如user:session:采用 “noeviction”,即使内存紧张也不淘汰会话缓存,保障登录状态稳定。
三、动态调整的实现与效果验证
ZKMall 通过 “监控工具 + 自动化脚本 + API 调用” 实现策略动态调整,无需人工干预,且通过实践验证了方案有效性。
1. 实现方式:自动化工具链集成
- 监控触发:Prometheus 配置告警规则(如商品缓存命中率 < 98% 持续 5 分钟),Alertmanager 调用自定义 Webhook 脚本。
- 策略决策:脚本根据告警类型(命中率下降 / 内存过高)、业务场景(商品 / 订单),从预设策略库匹配最优方案(如 “allkeys-lru” 切 “volatile-lru”)。
- 执行与审计:脚本通过 RedisCONFIG SET maxmemory-policy执行调整,记录调整日志(时间、旧策略、新策略、原因)至 Elasticsearch,便于后续追溯。
- 效果验证:调整后持续监控指标,10 分钟内未恢复则二次调整(如 “volatile-lru” 切 “noeviction”)并升级告警。
2. 实践效果:核心指标显著优化
- 缓存命中率:商品类从 95% 升至 98.5%,订单类从 92% 升至 96%,用户类从 96% 升至 99%,整体稳定在 98% 以上,较固定策略提升 3-5 个百分点。
- 接口响应时间:商品详情页从 80ms 降至 55ms,订单列表从 120ms 降至 70ms,用户登录从 60ms 降至 40ms,均控制在 100ms 内。
- 数据库压力:缓存穿透导致的数据库查询量减少 75%,CPU 使用率高峰时从 90% 降至 60% 以下,避免过载问题。
- 内存利用率:Redis 内存使用率从 90% 以上降至 80%-85%,内存浪费率(低频数据占比)从 25% 降至 10%,资源利用更高效。
3. 典型案例:双 11 促销策略调整
- 预热阶段(11.1-11.10):商品类缓存内存使用率达 88%,自动将 “allkeys-lru” 切 “volatile-lru”,淘汰 30% 冷门商品缓存,内存使用率降至 82%,预留高峰缓存空间。
- 高峰阶段(11.11 0:00-2:00):热门商品缓存每秒访问 5 万次,命中率短暂降至 97%,立即切 “noeviction” 并预热备用节点,10 分钟内命中率恢复至 99%。
- 回落阶段(11.11 20:00 后):订单缓存内存使用率达 89%,自动切 “volatile-lru”,优先保留近期订单缓存,数据库订单查询量减少 60%。
Redis 淘汰策略在 ZKMall 的动态调整实践,核心是 “以业务价值为导向,用动态机制适配变化”。通过按业务场景分类适配策略、结合周期与监控动态调整、按键前缀精细化控制,既解决了固定策略的刚性问题,又最大化发挥了 Redis 缓存价值。这一实践表明,缓存管理并非单纯技术配置,而是需深度结合业务特性,通过动态调整实现 “资源高效利用 + 用户体验保障” 的双重目标,为开源商城的缓存架构优化提供了可复用的参考方案。