这是一个基于 Spring Boot + MyBatis-Plus + MySQL + Redis 实现的黑马点评后端实战项目。
本项目在原有黑马点评业务的基础上,重点围绕 Redis 高并发场景、缓存设计、分布式登录态、社交互动、秒杀异步化、AI 智能体接入 等方向进行了完整实践。
项目不是单纯完成接口 CRUD,而是将真实后端开发中常见的问题串联起来:
- 如何使用 Redis 缓解数据库访问压力
- 如何处理缓存穿透、缓存击穿、缓存雪崩
- 如何将 Session 登录改造为 Redis Token 登录
- 如何使用 Redis 多种数据结构完成点赞、签到、共同关注、附近商铺、Feed 流等业务
- 如何将秒杀下单从同步数据库链路改造成 Redis 原子校验 + Stream 异步下单
- 如何在高并发场景下保证库存正确、一人一单、异常消息可补偿
- 如何通过 Dify 智能体将后端接口包装成自然语言可调用的业务工具
整体来看,本项目更偏向 Redis 全场景综合训练 + 后端业务建模 + AI Agent 工具调用实践,适合作为 Redis、秒杀系统、分布式登录、异步削峰、智能体接入后端服务的综合练习项目。
项目中不是简单地实现“查 Redis,查不到再查数据库”,而是针对不同缓存问题进行了分层处理:
- 缓存穿透:商铺不存在时缓存空值,避免非法请求反复击穿数据库
- 缓存击穿:热点商铺缓存重建时,使用自定义 Redis 分布式锁控制并发重建
- 缓存雪崩:为部分缓存 TTL 增加随机值,降低大量 Key 同时过期的风险
- 缓存更新:商铺信息更新时采用“先更新数据库,再删除缓存”的策略,降低脏数据风险
通过这些处理,项目从简单缓存查询升级为更接近真实业务的缓存设计方案。
项目将验证码、登录 Token、用户信息统一存入 Redis,解决了传统 Session 在多实例部署下无法共享的问题:
- 手机号验证码存入 Redis
- 登录成功后生成随机 Token
- 用户信息脱敏后以 Hash 结构存入 Redis
- 请求进入系统后通过拦截器解析 Token
- 用户信息保存到 ThreadLocal,供后续业务方法使用
- 每次请求刷新 Token TTL,实现滑动过期效果
这种方案更接近真实项目中的无状态登录设计,也方便后续进行多实例部署和网关扩展。
秒杀模块是本项目的核心高并发亮点之一。
传统秒杀请求如果直接进入数据库,会在高并发下频繁执行查库存、查订单、扣库存、写订单等操作,数据库压力较大。因此本项目将秒杀链路拆成两段:
在 Redis 层通过 Lua 脚本完成:
- 校验秒杀券库存是否充足
- 校验用户是否已经下过单
- 原子扣减 Redis 库存
- 原子记录用户购买标记
- 写入 Stream 异步订单消息
Lua 脚本保证这些操作在 Redis 中一次性执行完成,避免 Java 多次请求 Redis 带来的并发不一致问题。
Lua 校验通过后,订单消息进入 Redis Stream,由后台消费者异步处理:
- 后台线程读取订单消息
- 调用事务方法创建订单
- 数据库中扣减库存
- 插入订单记录
- 成功后 ACK 确认消息
- 异常时处理 Pending List,尽量避免消息丢失
这条链路将高并发请求先挡在 Redis 层,再将数据库写入操作异步削峰,降低数据库瞬时压力。
项目不是只把 Redis 当缓存,而是将 Redis 多种数据结构映射到了不同业务场景:
- String:验证码、商铺缓存、秒杀库存
- Hash:登录用户信息、秒杀时间窗口
- List:商铺类型缓存
- Set:关注关系、共同关注、一人一单标记
- ZSet:博客点赞排行、Feed 流收件箱
- Bitmap:用户签到、连续签到统计
- GEO:附近商铺查询
- Stream:秒杀异步订单队列
这部分可以体现出 Redis 不只是缓存工具,也可以参与业务建模、异步削峰和高并发控制。
在原有后端接口基础上,项目扩展接入了 黑马点评 AI 导购智能体,用于将自然语言请求转化为后端业务接口调用。
智能体主要用于:
- 根据用户输入查询附近商铺
- 根据店铺名称或店铺 ID 查询商铺优惠券
- 判断优惠券中是否存在秒杀券
- 根据秒杀券 ID 发起秒杀下单
- 将后端接口返回的 JSON 数据整理成用户能看懂的自然语言结果
智能体技术链路主要包括:
- Dify Agent / Workflow:负责任务编排、节点流转和工具调用
- 大模型节点:负责理解用户意图、判断应调用哪个业务能力
- HTTP Request 节点:负责调用 Spring Boot 后端接口
- 工作流变量 / 会话变量:保存店铺 ID、优惠券 ID、authorization 等内部状态
- authorization 变量透传:将前端已有登录态作为内部变量传入后端接口,不直接暴露给用户
- 结果整理节点:将后端返回体转换为自然语言说明,避免直接把原始 JSON 抛给用户
该智能体本质上不是替代后端业务逻辑,而是作为后端接口之上的自然语言调用层。真正的登录校验、库存校验、一人一单、秒杀下单、数据库写入仍然由 Spring Boot 后端负责,智能体只负责理解用户请求、选择工具、传递参数和整理结果。
- Spring Boot 3.2.0
- MyBatis-Plus 3.5.15
- Spring Web
- Spring Data Redis
- Lombok
- Hutool
- AspectJ
具体版本以
pom.xml为准。
- MySQL
- Redis
- Redisson
- Dify Agent / Workflow
- HTTP Request 工具节点
- 大模型意图识别与结果整理
- 工作流变量与会话状态管理
- 后端接口 authorization 鉴权透传
- Java 21
- Maven
- Redis Server
- MySQL Server
- 手机号验证码登录
- Redis Token 登录态管理
- 拦截器鉴权
- Token TTL 自动刷新
- ThreadLocal 保存当前登录用户
- 用户签到
- 连续签到统计
- 商铺详情查询
- 商铺缓存
- 商铺信息更新后删除缓存
- 按分类分页查询商铺
- 基于 Redis GEO 的附近商铺查询
- 商铺类型列表查询
- 使用 Redis List 缓存商铺类型
- 降低高频基础数据对数据库的访问压力
- 热门博客查询
- 博客详情查询
- 发布探店博客
- 博客点赞 / 取消点赞
- 点赞用户列表
- 基于关注关系的 Feed 流推送
- 滚动分页查询关注博文
- 关注 / 取关
- 是否关注判断
- 共同关注查询
- Redis Set 加速共同关注计算
- 新增秒杀券时同步写入 Redis 库存
- 新增秒杀券时同步写入 Redis 时间窗口
- Lua 脚本原子校验库存与一人一单
- Redis Stream 异步消费订单
- 事务创建订单
- Pending List 异常消息补偿
- 数据库库存扣减与唯一约束兜底
- 自然语言查询商铺
- 自然语言查询店铺优惠券
- 根据店铺 ID 或店铺名称调用后端接口
- 自动识别普通优惠券与秒杀优惠券
- 秒杀下单时传递内部 authorization 变量
- 将后端响应整理为用户可读结果
用户请求验证码时,将验证码存入 Redis。
用户登录成功后,系统生成随机 Token,并将脱敏后的用户信息以 Hash 结构存入 Redis。
这样可以避免在服务器本地 Session 中保存用户状态,也解决了多实例部署时 Session 不共享的问题。
商铺查询优先读取 Redis:
- 命中缓存,直接返回商铺信息
- 未命中缓存,查询数据库并回写 Redis
- 数据库也不存在时,缓存空字符串,防止缓存穿透
- 热点数据缓存重建时,使用 Redis 分布式锁控制并发
- 回写缓存时设置 TTL,并通过随机值降低雪崩风险
商铺类型属于高频读取、低频变更的数据,因此使用 Redis List 进行缓存,减少重复查询数据库。
项目使用 Redis GEO 存储店铺地理位置,通过用户经纬度进行半径查询,拿到商铺 ID 与距离后,再回表查询商铺详情并组装返回结果。
这种方式比直接在数据库中做复杂地理计算更适合高频附近查询场景。
博客点赞使用 Redis ZSet 实现:
- member:用户 ID
- score:点赞时间戳
这样既可以快速判断用户是否点赞,也可以按照点赞时间查询前几名点赞用户。
关注关系除了写入数据库,也同步写入 Redis Set。
共同关注查询时,可以直接使用 Set 交集运算完成,避免多次查表后再在 Java 内存中做比对。
用户发布博客后,系统会将博客 ID 推送到粉丝的 ZSet 收件箱中:
key:blog:feed:{userId}
member:blogId
score:发布时间戳