# hmdp-plus **Repository Path**: java-up-up/hmdp-plus ## Basic Information - **Project Name**: hmdp-plus - **Description**: 🔥 🔥 热门推荐 🔥 🔥将黑马点评进行完全地重构升级,围绕优惠券秒杀与热点查询,补齐高并发稳定性、动态令牌、限流、消息可靠性与数据一致性闭环,并添加订阅通知、候补排队等新亮点功能,解决烂大街和亮点不足问题!并打造成真正企业级别实战项目,全面工程化落地。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: https://javaup.chat - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2025-10-28 - **Last Updated**: 2025-11-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: 春招, 秋招, 就业, SpringBoot, 高并发 ## README **开源不易,还请您点个Star 多谢!🎉** 对于 Java 程序员而言,项目是简历与面试的核心竞争力。仅停留在 CRUD 或 Demo 级项目,很难体现工程化能力与架构思维。“黑马点评” 这个项目相信对于很多人来说并不陌生,甚至它是很多人开始学习 Java 语言的启蒙实战项目,也有不少人用它去面试,拿到了 Offer。它把“八股文”转化为可落地的工程方案:不背答案,直接在项目中应用与验证。 ## 黑马点评项目介绍 黑马点评是“本地生活与商户运营”场景的综合实战项目,包含商户浏览与查询、优惠券发放与抢购、达人探店、好友关注、签到与 UV 统计等核心业务。围绕“高并发下的优惠券秒杀”与“热点查询”的真实问题,提供端到端的稳定性与一致性解决方案。 ## 黑马点评功能回顾 **主要重点围绕 Redis 的多种数据结构与实战场景展开:** - **短信登录:** 基于 Redis 共享 Session 实现分布式会话管理。 - **商户查询缓存:** 认知并实战缓存穿透、缓存击穿、缓存雪崩问题的应对方式。 - **优惠券秒杀:** 基于 Redis 计数器 + Lua 的原子扣减;理解分布式锁(含 Redisson);掌握三种消息队列的用法与对比。 - **附近的商户:** 使用 Redis GEO 实现地理位置检索与排序。 - **UV 统计:** 使用 HyperLogLog 完成海量去重统计。 - **用户签到:** 利用 BitMap 进行用户签到与统计。 - **好友关注:** 基于 Set 实现关注、取消关注、共同关注等社交关系。 - **达人探店:** 用 List 实现点赞列表,用 SortedSet 实现点赞排行榜。 **库存扣减相关功能**: - 优惠券秒杀中的库存超卖问题与乐观锁方案。 - Redis 分布式锁与 Redisson 锁的选型与用法。 - 使用 Redis 判断秒杀资格与消息队列的简单应用。 ## 黑马点评的问题 黑马点评项目作为练手学习来说,很不错能够快速进入实战,但是要拿去面试使用,特别是要面大厂的话,就有点不够看了,很容易问到: - **流量突发时,如何动态的限流?** - **Redis宕机了怎么办?** - **Redis数据丢失了怎么办?** - **MQ宕机了怎么办?** - **MQ消息丢失了怎么办?** - **MQ消息延迟消费了怎么办?** - **数据库的库存数量和Redis中的不一致怎么办?** - **Redis恢复后,丢失的数据要怎么恢复?** 这些问题在黑马点评中并没有得到解决,而恰恰这些还正是大厂特别看中的 **“解决问题的能力”**,所以本人推出 **黑马点评 Plus 版本**,来解决这些疑难重症,并且额外再引入新的功能,让这个项目彻底的无懈可击! 点评中并没有得到解决,而恰恰这些还正是大厂特别看中的 “解决问题的能力”,所以本人推出 **黑马点评 Plus 版本**,来解决这些疑难重症,并且额外再引入新的功能,让这个项目彻底的无懈可击! # 一、黑马点评 Plus 是什么 🚀 首先,黑马点评 Plus 将 SpringBoot 版本升级到了主流成熟的 SpringBoot3,并将其他的中间件,如:MybatisPlus、Redis、Redisson、Kafka都升级到了最新版本。 并且功能在普通版能力的基础上,补齐 **“高并发稳定性、限流功能、令牌的发送、数据一致性保障、可观测与故障闭环”** 等多种维度 ### 黑马点评 Plus 项目详细讲解 🔗:[👉 点击查看讲解](https://www.javaup.chat/hmdp-plus/overview/project-change) - 🚦 **全链路流控:** 令牌前置授权 + 令牌桶限流,将“资格判断”与“流量控制”前置到入口,显著降低突发流量对系统的冲击。 - 🗄️ **多层缓存策略:** 本地缓存 + Redis 缓存 + 空值缓存 + 布隆过滤器,有效降低 DB 压力与热点击穿风险。 - ✅ **缓存问题的完美解决:** 多层缓存与双重锁检测,辅以空值缓存与布隆过滤器,弥补普通版本的不足,彻底缓解穿透与击穿。 - 🔁 **一致性闭环:** Redis 扣减、订单创建、消息投递、数据库落库之间建立明确的状态流转与补偿策略。 - 📦 **MQ 可靠性:** 发布确认、重试退避、死信与延迟队列、消费幂等与去重,提升消息处理鲁棒性。 - 🔍 **可观测与故障分析:** 聚焦链路瓶颈、异常源定位与版本压测对比,形成闭环优化机制。 - 📈 **运营能力:** 支持“每日 Top 买家”和“订阅-通知-领取”的活动玩法,提升用户参与度与复购。 - 🗂️ **分库分表与路由设计:** 分库分表与全局 ID 生成,订单与对账日志按需拆分,为数据规模增长与高并发写入提供保障。 ![](https://multimedia-javaup.cn/hmdp-plus/%E6%80%9D%E7%BB%B4%E5%AF%BC%E5%9B%BE.png) # 二、Plus 版本解决了普通版本的哪些问题与痛点! ## 2.1 抢购业务的关键痛点 ![](https://multimedia-javaup.cn/hmdp-plus/%E7%A7%92%E6%9D%80%E4%BC%98%E6%83%A0%E5%88%B8.png) - **流量入口缺少前置控制** - ⚠️ **问题:** 缺乏权限令牌与令牌桶限流,突发洪峰直接压垮热点接口。 - 🔹 **Plus 方案:令牌前置授权与令牌桶限流,支持动态阈值与人群优先级(如 VIP)。** - **扣减链路缺少一致性闭环** - ⚠️ **问题:** Redis 扣减成功但订单创建失败、消息未投递或延迟,导致库表与缓存不一致。 - 🔹 **Plus 方案:Redis记录、本地消息表、订单对账日志、定时一致性校验与补偿队列,消费端幂等与去重。** - **MQ 可靠性不足** - ⚠️ **问题:** 使用 RedisStream,宕机后消息丢失,无发布确认、重试退避、延迟/死信队列,消息丢失/重复/乱序未处理。 - 🔹 **Plus 方案:使用 Kafka,并在生产端/消费端确认、指数退避重试、DLQ/延迟队列、消费幂等、发送失败/消费失败/消费超时的各种处理。** - **数据层扩展不足** - ⚠️ **问题:** 订单等热点数据未分库分表,大数量情况下性能低下,读扩散与热点聚集难抑制。 - 🔹 **Plus 方案:Sharding 路由、全局 ID 生成、分片内对账与差异补偿。** - **故障场景处理缺失** - ⚠️ **问题:** Redis 主从切换数据丢失、Lua 宕机、扣减成功但订单失败 等没有对应的处理策略。 - 🔹 **Plus 方案:消息记录信息、操作日志记录、可重入脚本设计、补偿扫描与自动回滚机制。** ## 2.2 扩展性的关键痛点 ![](https://multimedia-javaup.cn/hmdp-plus/%E4%BC%98%E6%83%A0%E5%88%B8%E7%9A%84%E6%9F%A5%E8%AF%A2.png) - **分布式锁使用粗糙** - ⚠️ **问题:** 锁的设计类型单一,没有考虑到多种锁类型,锁超时处理方式。 - 🔹 **Plus 方案:对 Redisson 重构设计,支持的锁类型:读锁、写锁、公平锁、非公平锁。锁的使用:注解化、命令式、方法级。可自定义处理失败策略。** - **缓存策略单一** - ⚠️ **问题:** 缓存穿透/击穿的解决方案不够完美:仅依赖单层 Redis,未引入空值缓存、布隆过滤器、本地缓存与逻辑过期。 - 🔹 **Plus 方案:本地 + Redis 双层缓存、空值缓存、布隆过滤器、双重锁检测、逻辑过期与异步重建。** - **运营策略不足** - ⚠️ **问题:** 缺少 Top 买家统计、订阅通知与开抢前预通知,拉新促活能力有限。 - 🔹 **Plus 方案:SortedSet 榜单、ZSet 订阅、Redisson 延迟队列分片设计提高效率,执行预通知与去重控频,降噪通知。** - **可观测性薄弱** - ⚠️ **问题:** 缺少耗时画像、异常聚合、版本压测对比,难以定位瓶颈与评估优化。 - 🔹 **Plus 方案:链路埋点、请求画像与异常聚合,关键接口压测与版本对比报告。** # 三、如何启动项目 - [准备项目启动条件](https://javaup.chat/hmdp-plus/startup/prerequisites) - [如何安装项目需要的中间件环境](https://javaup.chat/hmdp-plus/startup/install-middlewares) - [后端项目部署启动](https://javaup.chat/hmdp-plus/startup/backend-deploy) - [前端项目部署启动](https://javaup.chat/hmdp-plus/startup/frontend-deploy) - [项目文档和视频目录](https://javaup.chat/hmdp-plus/overview/project-change) # 四、关键问题解决的能力详解 ## 4.1 缓存穿透与缓存击穿的组合解法 **核心思路:** 在读取链路中构建“多道防线”,保证数据库与热点数据的稳定性。 ### 1) 防穿透 : - **空值缓存:** 数据库查不到时,将空结果写入 Redis,设置短 TTL,避免同一非法键反复打到 DB。 - **布隆过滤器:** 将合法 ID 集合放入布隆过滤器,拦截绝大多数非法请求(误判率可控)。 ### 2) 防击穿 : - **本地缓存 + Redis 缓存:** 双层缓存减少瞬时热点对 Redis 的压力,降低跨网络成本。 - **双重锁检测(Double-Check-Locking):** 只有一个线程进入重建逻辑,其余线程走缓存或短路返回,避免并发重建风暴。 - **逻辑过期与异步重建:** 热点数据过期时不立刻失效,先返回旧值,再异步重建新值,削峰填谷。 - **预热与热点标记:** 提前将热门商户/优惠券加载至缓存,结合定时刷新与失效策略。 ### 3) 读流程参考(简化伪流程) : ``` 查本地缓存 → 命中返回 未命中 → 查布隆过滤器(非法直接空值返回) 合法 → 查 Redis(命中返回;空值则短路返回) Redis 未命中 → 获取重建锁 → 双重检查 → 负载保护 + DB 查询 → 写入空值/实体缓存 → 释放锁 → 返回 ``` ## 4.2 令牌前置授权 + 令牌桶限流 - **权限令牌:** 抢购前先申请“权限令牌”,未持有令牌者不进入扣减链路,保障后端资源。 - **令牌桶:** 在入口按速率放行请求,避免瞬时洪峰压垮系统;支持动态桶容量与优先级(VIP/历史高价值用户)。 - **实现要点:** 基于 Redis 的限流器,实现分布式环境下的统一流控;令牌与资格在 Redis 中统一管理与过期清理。 ## 4.3 Redis 架构问题与故障闭环 **典型问题与应对:** - **扣减成功后服务宕机:** 使用“扣减记录 + 事务外的可靠投递(Outbox)”模型,服务恢复后自动补发消息并对账。 - **Lua 执行过程中宕机:** Lua 脚本设计幂等与可重入;扣减与记录整体原子;补偿任务扫描半事务状态进行回滚或重试。 - **主从切换的数据丢失:** 评估复制与持久化策略(AOF/RDB),关键扣减记录落地到“对账日志”并周期性校验。 - **Redis 与数据库对账:** 引入“扣减记录表/订单对账日志表”,按照订单流水与扣减流水做一致性比对,差异项进入补偿队列。 - **数据库有订单、Redis 丢数据:** 按订单路由表回查对应分片,补写 Redis 或同步触发补偿流程。 - **Redis 扣减成功但订单创建失败:** 消费端幂等 + 事务边界控制,失败写入对账日志并触发补偿(回滚余票或再次下单)。 ## 4.4 MQ 架构问题与一致性保障 **围绕“扣减 → 下单 → 通知/发券”的链路设计消息可靠性:** - **生产端:** 发布确认(Confirm)、失败回退与重试(指数退避),消息持久化(可靠队列)。 - **消费端:** 幂等处理(基于业务唯一键与去重表)、异常重试、死信队列(DLQ)隔离。 - **延迟队列:** 用于“开抢前预通知”“订单超时关闭”等场景。 - **一致性策略:** 配合 Outbox 模式或本地消息表,实现“写库成功即投递消息”的最终一致性。 - **乱序与延迟:** 在消费端做版本校验或时间窗容忍策略,保障数据与状态不被旧消息覆盖。 ## 4.5 请求疑难杂症与链路观测 - **废弃订单获取:** 按订单状态与超时时间进行清理与标记,沉淀“废弃订单视图”,供运营与对账使用。 - **链路耗时分析:** 埋点统计每个关键步骤耗时,生成请求画像,识别瓶颈(DB/Redis/MQ/锁等待等)。 - **异常定位:** 将错误栈与请求上下文相关联,按版本/接口/商户维度聚合,提升排障效率。 - **压测画像:** 对“节目详情”“生成订单”等关键接口做版本化压测报告,横向对比优化效果。 ## 4.6 分库分表设计与路由 - **拆分对象:** 用户表、用户信息表、用户手机号表、优惠券表、秒杀优惠券表、优惠券订单表、订单路由表、订单对账日志表。 - **路由策略:** 按用户或店铺维度做分片,订单类表按订单号或用户 ID 做路由,保证热点均衡与查询可达。 - **全局 ID:** 引入全局 ID 生成器(如雪花、号段、Leaf 等),保障跨分片唯一性与有序性。 - **对账与补偿:** 定时任务在分片内做一致性校验,差异项进入补偿流程,结合 MQ 与 Redis 进行回滚或重试。 ![](https://picture-1306508146.cos.ap-beijing.myqcloud.com/hmdp-plus/%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8.png) ## 4.7 统计“店铺每日 Top 买家” - **设计:** 每个店铺每天一个 Key,采用 SortedSet 记录用户购买额或订单数,分值为贡献值,成员为用户 ID。 - **写入:** 订单创建成功后写入统计集;设置合理 TTL(如 7~30 天)以控制存储;每日零点归档与榜单快照。 - **展示:** 支持按店铺维度查询 TopN;可结合用户等级做营销触达。 ## 4.8 订阅通知(余票补充与取消回流) - **设计:** 当库存不足时,用户加入订阅集合(ZSet,分值为订阅时间或优先级)。 - **触发:** 库存补充或订单取消回流时,按订阅时间最早(或优先级最高)挑选用户,发送通知或自动为其保留资格。 - **保障:** 通知链路纳入 MQ 可靠投递与延迟重试;控制幂等,避免重复通知。 ## 4.9 通知领取(开抢前 2 分钟预通知) - **延迟队列:** 使用 Redisson 重构优化的延迟队列在活动开始前 2 分钟发送消息。 - **人群:** 从“用户等级集合”“每日 Top 买家”集合中抽取用户,支持随机与优先级混合策略。 - **去重与速率控制:** 保证通知不重复与速率不超限,维护良好用户体验与系统负载。 ![](https://multimedia-javaup.cn/hmdp-plus/%E8%AE%A2%E9%98%85%E9%80%9A%E7%9F%A5.png) # 五、架构设计的能力详解 🏗️ ## 5.1 MQ 组件设计 - **目标:** 为“扣减 → 下单 → 通知/发券”等链路提供可靠消息能力,覆盖生产确认、重试退避、死信隔离、延迟/定时消息与全链路可观测。 - **可靠投递与一致性:** - 采用 Outbox 模式(本地消息表):业务事务提交后写入 Outbox,由异步分发器投递至 MQ,保障“写库成功即可投递”的最终一致性。 - 消息状态机:`PENDING → SENT → ACKED/FAILED`;失败进入重试,超过阈值入 DLQ(死信队列),支持人工与自动回溯。 - **成功情况的处理:** 在消息发送成功、消费成功,都有灵活的扩展钩子,方便后续埋点与监控。 - **各种失败情况的考虑:** 当消息发送失败、消费超时、消费异常、消费失败,等各种失败异常的情况,都有对应的扩展策略,回滚、补偿、上报、通知等。 - **消费幂等与去重:** 以业务唯一键 `messageId`(uuid)为幂等键,结合幂等组件和幂等标识,避免重复消费影响状态。 - **可观测与运维:** 暴露发布/消费成功率、重试次数、DLQ 积压量、端到端耗时等指标;提供“停车场(parking-lot)”模式对个别异常消息人工处置。 ![](https://multimedia-javaup.cn/hmdp-plus/MQ%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1.png) ## 5.2 Redis 组件设计 - **目标:** 标准化缓存读写与热点治理,统一 Key 规范、TTL 策略、逻辑过期与异步重建、空值缓存与布隆过滤器、L1+L2 双层缓存。 - **读写流程与策略:** - 读:本地缓存 → 布隆过滤器 → Redis 命中返回;未命中走“重建锁 + 双重检查 + 负载保护 + DB 查询”,写回实体或空值缓存。 - 过期:逻辑过期优先,热点数据先返回旧值再异步重建,削峰填谷;普通数据按 TTL 自然失效。 - 预热:活动前/热点店铺提前预热,定时刷新与冷热迁移。 - **降级与容错:** 支持开关与熔断,异常时走短 TTL 的降级数据或直接回源 DB;关键写路径配合对账日志保障一致性。 - **布隆与空值缓存:** 布隆过滤器拦截非法键;空值缓存避免穿透风暴,结合短 TTL 与访问计数自动清理。 - **可观测指标:** 命中率、重建次数/耗时、锁等待、空值比、热点 TopN、序列化开销等。 ## 5.3 Redis 限流与令牌桶组件设计 - **目标:** 在分布式环境下提供高性能、可配置、可观测的令牌桶限流,支撑入口流控与“令牌前置授权”协同。 - **限流维度:** 支持按 `IP/用户/接口/店铺/活动` 等维度限流,组合维度形成精细化配额;支持突发 `burst` 与滑动窗口辅助。 - **优先级与白名单:** 支持 VIP/历史高价值用户优先配额、白名单/黑名单、动态在线配置与热更新。 - **与令牌前置授权协同:** 抢购前需获取“资格令牌”(Redis 统一管理与过期),进入扣减链路前再经令牌桶放行,实现“资格控制 + 速率控制”的双重保障。 - **接入方式与返回契约:** 网关/接口统一拦截器,调用是否放行及剩余配额;拒绝时返回原因码与重试建议。 - **监控与告警:** 暴露限流触发次数、放行比、剩余令牌、拒绝原因分布等指标;异常突增触发告警与应急限流策略。 表关系 ## 5.4 布隆过滤器的设计 - **目标:** 在读链路前置拦截非法 Key/ID,降低缓存穿透与数据库压力,确保热点场景下的稳定性。 - **核心抽象:** 统一封装添加、存在性判断、批量初始化与误判率配置、按业务分区管理。 - **构建与维护:** - 初始化:基于数据库合法 ID 集合批量加载;支持分批/分片加载,避免长事务与阻塞。 - 增量:新资源上线/变更时通过任务/消息增量写入,保证线上布隆与真实集合一致性收敛。 - **接入点与协同:** - 在缓存读取前进行 `mightContain(id)` 判断;不存在直接返回空值或错误码,存在则继续缓存/DB 链路。 - 与“空值缓存”“缓存客户端”协同,形成防穿透的双保险。 - **可观测与参数:** 支持误判率、容量与哈希函数数量的动态配置;暴露阻断率、误判样本率与重建开销。 ## 5.5 分布式锁的设计 - **目标:** 为热点重建、扣减/下单关键段提供互斥控制,避免并发写冲突与重建风暴。 - **锁模型与语义:** - 可重入锁与租约(leaseTime)控制,自动续期(看门狗)保障长耗时任务不被误释放。 - `tryLock(timeout)` 与 `lock()` 两种语义,支持阻塞/非阻塞与超时回退策略。 - **接入策略:** - 双重检查 + 锁:重建热点数据前获取锁,完成后释放;失败降级返回旧值或短 TTL 数据。 - 关键扣减段使用细粒度锁(按活动/店铺/券),避免大锁引发串行化与吞吐下降。 - **锁类型:** 支持读锁、写锁、公平锁、非公平锁,满足不同场景需求。 - **锁的使用:** 提供注解方式、命令式方式、方法级锁等多种接入方式,方便业务方使用。 ![](https://multimedia-javaup.cn/hmdp-plus/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81.png) ## 5.6 分布式幂等功能的设计 - **目标:** 防重复提交/重复消费,保障“最多一次/恰好一次”的业务语义,降低并发抖动带来的状态污染。 - **核心抽象:** 注解式接入:,无侵入保护 Controller/Service 方法。 - **优化策略:** 引入本地锁的功能,实现在同一实例下快速幂等。 - **应用场景:** 下单接口防重复、MQ 消费端防重、通知发放防重;结合“Outbox + 幂等”形成一致性闭环。 - **异常与反馈:** 幂等冲突返回明确原因码与重试建议;自动过期释放。 ## 5.7 分布式延迟队列的设计 - **目标:** 提供高可靠的定时/延迟任务能力,覆盖“开抢前预通知”“订单超时关闭”“补货触达”等场景。 - **核心抽象:** 提交/拉取/消费接口,支持批量与并发度控制。 - **实现机制:** 在 Redisson 延迟队列基础下,进行分片拆分设计与线程池结合异步消费,极大提高执行效率。 - **一致性保障:** 与 Outbox/本地消息表协同,确保“写库成功即产生延迟任务”;消费幂等与去重策略同 MQ 模块。 - **接入示例:** 活动开始前 2 分钟预通知、订单超时自动关闭与库存回流、订阅用户按优先级触达。 - **监控与运维:** 队列积压量、到期偏差、任务成功率与重试次数;异常任务进入“停车场”人工处置。 # 六、各种中间件宕机和数据丢失的解决方案 将真实生产环境中遇到的宕机问题、数据丢失、问题排查等实际逻辑的解决的方案,都会在黑马点评 Plus 版本中进行应用。 表关系 # 七、前端新功能的添加 黑马点评 Plus 不仅在后端做了大量的改进和优化,同时在前端也新增了一些功能,提升用户体验和系统的整体性能。 ## 7.1 抢购优惠券前的流程优化 在抢购优惠券的过程中,重新将页面样式进行了优化,提升了用户的视觉体验。 表关系 ## 7.2 抢购优惠券过程中的提示优化 在抢购优惠券的过程中,会弹出提示框,提示用户正在抢购中,只有在真正的抢购成功后,才会告知用户抢购成功,否则会提示抢购失败。 表关系 ## 7.3 如果抢购成功,后续还可以取消 在抢购成功后,用户可以选择取消抢购的优惠券,这样可以提升用户的灵活性和体验。 表关系 ## 7.4 到券提醒 如果优惠券被售罄了,用户还可以选择“到券提醒”,当有新的优惠券放出来时,系统会自动通知用户。 表关系 ## 7.5 订阅通知 当用户选择“到券提醒”后,系统会通知用户已订阅到券提醒。 表关系