RedisMall实战项目上线,SpringBoot3.5.9环境下演示热点问题解决方案
开发者开源 Redis Mall 项目,基于 Spring Boot 3.5.9 与 JDK 21,通过可交互界面直观呈现缓存穿透、击穿、雪崩、超卖等典型问题的代码实现与应对策略,涵盖 Cache-A...
一个名为 Redis Mall 的开源实战项目近日上线,旨在将 Redis 在高并发场景下的常见问题具象化为可操作、可对比、可验证的工程实践。该项目由开发者 iweidujiang 构建,运行于 Spring Boot 3.5.9 与 JDK 21 环境,核心目标是让工程师在浏览器中直接观察缓存失效、数据库压力激增、库存超卖等现象,并理解对应解决方案的代码逻辑与边界条件。
项目采用模拟内存数据库 ProductStore,每次查询强制延迟 30ms 并计数,便于量化“打到 DB 多少次”,从而清晰区分缓存命中与回源行为。预置三款商品(ID 1001–1003),库存以 stock:{id} 形式存于 Redis,接口设计覆盖商品详情、改价、下单等典型电商链路。
在商品详情读取环节,项目严格遵循 Cache-Aside 模式:先查 Redis,若返回 NIL(即明确标记“已查无”),则不再访问数据库;仅当缓存为空且未标记存在时,才调用 loadWithMutex 进行回源加载。这一设计有效规避了缓存穿透——对不存在的商品 ID(如 product:9999999)反复请求不会持续冲击数据库。系统启动时将真实商品 ID 写入布隆过滤器,作为第一道拦截闸门;第二道则依赖缓存层的空值标记(如 __nil__),确保“查过无”的结果被持久化,避免重复穿透。
改价逻辑同样体现强一致性优先原则:先更新内存数据库中的价格,再删除对应缓存键(DEL product:{id}),而非先改缓存后改库。此举防止数据库写入失败导致 Redis 中残留错误价格。值得注意的是,删缓存与下次回填之间存在短暂窗口期,高并发下可能出现旧值被重新写入缓存的情况。项目说明指出,该风险在商品详情页可接受(毫秒级不一致),但对库存、账户余额等强一致性场景必须禁用此模式。
下单环节聚焦库存超卖防控。项目明确反对“GET 库存 → 计算新值 → SET 回写”的非原子操作,而是采用 Lua 脚本实现扣减:以 stock:{id} 为 key,通过 DECRBY 或 CAS 逻辑一次性完成读-判-写,确保并发安全。测试时可通过 /api/scenarios/super-sell 页面触发高并发下单,直观对比有无 Lua 防护下的库存一致性差异。
限流功能集成于正式接口(如每分钟 100 次),而场景测试按钮不限流,便于复现极端压力。项目提供 redis-cli 实时观测手段,例如通过 TTL product:1001 查看缓存存活时间是否落在 300–360 秒区间(写入时添加随机偏移防集体过期),或监控大 Key 与热 Key 的分布情况。其中热 Key 检测结合了 Redis 的热点统计机制与自定义埋点,帮助定位突发流量集中点。
项目左侧导航栏设七个独立场景模块:商品与缓存、穿透、击穿、雪崩、超卖、限流、大 Key/热 Key,支持并排对比“正确路径”与“错误路径”的执行效果。例如,在“击穿”场景中,可模拟某热门商品缓存过期瞬间大量请求涌入,观察是否触发互斥锁(mutex)保护;在“雪崩”场景中,人为设置多个 key 同一时刻过期,验证随机 TTL 策略是否缓解了数据库瞬时压力。
从技术栈看,该项目未引入额外中间件,仅依赖 Spring Data Redis 与原生 Jedis/Redisson 封装,代码结构清晰,适合作为教学参考或团队内部演练素材。其价值不仅在于展示“怎么做”,更在于揭示“为什么不能那样做”——例如,为何不能先改缓存再改库?为何空值必须标记而非简单忽略?这些决策背后是对数据一致性、系统可用性与运维可观测性的综合权衡。
当前,Redis 仍是 Java 生态中缓存层的事实标准,而 Spring Boot 的自动配置极大降低了集成门槛。但正如该项目所强调的,框架封装掩盖了底层复杂性,真正的挑战在于业务语义与缓存策略的精准匹配。当商品详情允许短暂不一致时,Cache-Aside + 空值缓存是高效选择;当涉及资金或库存时,必须升级为读写锁、分布式锁或事务型缓存方案。
开源地址已公开于 GitHub(github.com/iweidujiang…),鼓励开发者 fork、调试与扩展。随着微服务架构普及与实时性要求提升,此类“问题驱动型”工程示例正成为一线工程师快速校准认知偏差的重要工具。项目虽小,却完整覆盖了从缓存设计、异常防护到压测验证的闭环链条,为 Spring Boot 项目中的 Redis 实战提供了可落地的参照系。
