Skip to content

00 - 项目总览与架构

知识图谱

┌─────────────────────────────────────────────────────────────────┐
│                        hmdp - 黑马点评                          │
│              Spring Boot 2.3.12 / Java 8 / Maven                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────┐  │
│  │   com.hmdp   │  │   com.like   │  │    External Services │  │
│  │   (主应用)    │  │  (点赞子系统) │  │                      │  │
│  ├──────────────┤  ├──────────────┤  │  ┌────────────────┐  │  │
│  │ Controller   │  │ Controller   │  │  │     MySQL      │  │  │
│  │ ├─ Shop      │  │ └─ Like      │  │  │  (数据持久化)   │  │  │
│  │ ├─ Blog      │  ├──────────────┤  │  ├────────────────┤  │  │
│  │ ├─ Voucher   │  │ Service      │  │  │     Redis      │  │  │
│  │ ├─ VouOrder  │  │ ├─ LikeBhvr  │  │  │  (缓存/锁/ID)  │  │  │
│  │ ├─ User      │  │ ├─ LikeArtCt │  │  ├────────────────┤  │  │
│  │ ├─ Follow    │  │ └─ LikeUsrCt │  │  │     Kafka      │  │  │
│  │ └─ ShopType  │  ├──────────────┤  │  │  (异步消息队列)  │  │  │
│  ├──────────────┤  │ Mapper       │  │  ├────────────────┤  │  │
│  │ Service      │  │ Event(Kafka) │  │  │   Redisson     │  │  │
│  │ ├─ Shop      │  └──────────────┘  │  │  (分布式锁框架) │  │  │
│  │ ├─ Blog      │                    │  └────────────────┘  │  │
│  │ ├─ VouOrder  │                    └──────────────────────┘  │
│  │ ├─ User      │                                              │
│  │ ├─ Follow    │  ┌──────────────────────────────────────┐    │
│  │ └─ Voucher   │  │         横切关注点 (Cross-Cutting)     │    │
│  ├──────────────┤  │                                      │    │
│  │ Utils        │  │  Auth: RefreshTokenInterceptor       │    │
│  │ ├─CacheClient│  │        LoginInterceptor              │    │
│  │ ├─SimpleRedis│  │  Cache: CacheClient (穿透/击穿/雪崩)  │    │
│  │ │  Lock      │  │         CaffeineCache (本地L1)        │    │
│  │ ├─RedisIdWrkr│  │  Lock:  SimpleRedisLock / Redisson   │    │
│  │ └─UserHolder │  │  ID:    RedisIdWorker (分布式ID)      │    │
│  ├──────────────┤  │  MQ:    KafkaOrderProducer/Consumer  │    │
│  │ Event(Kafka) │  └──────────────────────────────────────┘    │
│  │ ├─Producer   │                                              │
│  │ └─Consumer   │                                              │
│  └──────────────┘                                              │
└─────────────────────────────────────────────────────────────────┘

技术栈一览

层次技术用途
框架Spring Boot 2.3.12应用骨架
语言Java 8开发语言
ORMMyBatis-Plus数据库访问,IService/ServiceImpl 模式
数据库MySQL持久化存储
缓存Redis (StringRedisTemplate)分布式缓存、分布式锁、分布式ID、GEO查询
本地缓存CaffeineL1 本地热点缓存
分布式锁Redisson可重入锁、看门狗续期
消息队列Kafka秒杀异步下单、点赞事件处理
序列化Jackson (GenericJackson2JsonRedisSerializer)Redis value 序列化
工具库Hutool, Lombok简化开发
构建Maven依赖管理与构建

模块划分

主应用 com.hmdp

模块核心功能关联文档
商铺 Shop缓存查询(穿透/击穿)、GEO 附近商户01-Redis缓存09-GEO
博客 Blog发布、点赞(ZSet)、Feed流推送05-Feed流
优惠券 Voucher三种券(普通/限购/秒杀)、秒杀下单03-秒杀系统
用户 User登录注册、签到(Bitmap)、限流06-认证鉴权
关注 Follow关注/取关、共同关注(Set交集)08-关注与社交

点赞子系统 com.like

独立于主应用的模块,有自己的 Controller / Service / Mapper / Event。通过 @SpringBootApplication(scanBasePackages = "com") 统一扫描。

核心特点:三层判重(布隆过滤器 + Redis ZSet + DB)、Kafka 异步持久化、本地缓存预热。

详见 → 07-点赞子系统

请求生命周期

HTTP Request


RefreshTokenInterceptor (order=0, /**)
    │  提取 Token → Redis Hash → UserDTO → ThreadLocal
    │  刷新 Token TTL

LoginInterceptor (order=1, 排除公开路径)
    │  检查 ThreadLocal 是否有用户
    │  无用户 → 401

Controller
    │  参数校验,调用 Service

Service
    │  业务逻辑,操作 Redis / DB / Kafka

返回 Result(success/fail)


afterCompletion: UserHolder.removeUser() 清理 ThreadLocal

Redis 数据结构全景

数据结构Key 模式用途详见
Stringcache:shop:{id}商铺缓存01
Stringlogin:code:{phone}验证码06
Stringlock:shop:{id}缓存重建互斥锁02
Hashlogin:token:{UUID}用户会话06
Hashseckill:stock:{voucherId}秒杀库存/时间窗口03
Hashseckill:buyCount:{voucherId}用户购买计数03
Setseckill:order秒杀订单ID集合03
Setfollows:{userId}关注列表08
ZSetblog:liked:{blogId}博客点赞用户(按时间)05
ZSetfeed:{userId}用户Feed收件箱05
ZSetlikeZset:userId:{id}用户点赞文章列表07
ZSetlikeZset:articleId:{id}文章被赞用户列表07
Bitmapsign:{userId}:yyyyMM签到记录06
GEOshop:geo:{typeId}商铺地理位置09
BloomFilterlike-behavior-bloom-filter点赞行为快速判重07

Lua 脚本清单

脚本位置用途详见
seckill.luasrc/main/resources/seckill.lua原子扣减库存、校验时间窗口和限购03
rollback.luasrc/main/resources/rollback.lua秒杀失败时回滚 Redis 数据03
unlock.luasrc/main/resources/unlock.lua分布式锁原子释放(compare-and-delete)02
updateLikeCount.luasrc/main/resources/updateLikeCount.lua原子更新点赞计数07

Kafka Topic 清单

Topic生产者消费者用途详见
createOrderVoucherOrderServiceImplKafkaOrderConsumer秒杀异步下单03, 10
save-order-failed-topicKafkaOrderConsumerKafkaOrderConsumer下单失败回滚03, 10
TOPIC_LIKE_BEHAVIORLikeBehaviorServiceImplKafkaLikeConsumer点赞事件07, 10
TOPIC_SAVE_DB_FAILEDKafkaLikeConsumerKafkaLikeConsumer点赞持久化失败07, 10

面试 Q&A

Q1: 请介绍一下你的项目

这是一个类似大众点评的社交点评平台,核心功能包括商铺查询与缓存、优惠券秒杀、博客Feed流、用户关注、点赞等。

技术上,使用 Spring Boot + Redis + Kafka + Redisson 构建。重点解决了几个典型分布式问题:

  • 缓存穿透/击穿/雪崩:封装了通用 CacheClient,提供三种策略
  • 高并发秒杀:Redis Lua 脚本原子扣减 + Kafka 异步落库,实现读写分离
  • 分布式锁:从手写 SimpleRedisLock 演进到 Redisson
  • Feed流:基于 Redis ZSet 的推模式 + 游标分页
  • 点赞系统:独立子系统,布隆过滤器 + ZSet + DB 三层判重

追问:项目有几个模块?为什么点赞要独立出来?

两个 Java 根包:com.hmdp(主应用)和 com.like(点赞子系统)。

点赞独立出来是因为它在架构上可以作为独立微服务拆分——有自己的 Controller、Service、Mapper、Kafka Event,与主应用只通过 UserService 共享用户数据。这种设计为将来服务化做好了准备。

再追问:两个包是怎么被 Spring 同时扫描到的?

HmDianPingApplication 上配置了 @SpringBootApplication(scanBasePackages = "com"),同时 @MapperScan({"com.hmdp.mapper", "com.like.mapper"}) 扫描两个 mapper 包。

Q2: 项目中用到了哪些 Redis 数据结构?分别解决什么问题?

几乎用到了 Redis 全部核心数据结构:

  • String:缓存商铺数据、验证码存储、互斥锁、计数器
  • Hash:用户会话Token、秒杀库存信息
  • Set:关注列表(用于 SINTER 求共同关注)、秒杀订单集合
  • ZSet:博客点赞排行、Feed流收件箱、点赞记录
  • Bitmap:用户签到(每天1位,空间极优)
  • GEO:附近商户查询(5km 范围搜索)
  • Bloom Filter(Redisson):点赞行为快速判重

追问:为什么用 ZSet 而不是 List 做 Feed 流?

ZSet 支持按 score(时间戳)范围查询 + 自动排序,而 List 只支持下标访问。Feed 流需要按时间倒序分页,且要处理同一时刻多条消息的情况,ZSet 的 ZREVRANGEBYSCORE + offset 可以精确定位游标位置,List 做不到。


加分回答

  • 能画出完整的请求链路(从 HTTP 到 Redis/DB/Kafka)说明对架构理解深入
  • 主动提到项目中的设计取舍(如推模式 vs 拉模式、Lua vs 事务)展示批判性思维
  • 提到点赞子系统的独立设计暗示微服务拆分思路,面试官会认为你有架构意识
  • 主动列出项目中发现的 Bug(见 11-已知问题),展示代码审查能力

关联文档