一、设计短链系统
核心问题
把 https://www.example.com/article/123456789 变成 https://t.cn/Ab3dEf
答题框架
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| ① 需求澄清
- 日活多少?假设 1000万 DAU
- 短链有效期?假设永久有效
- 读写比例?读远大于写(100:1)
② 容量估算
- 每天生成短链:100万条
- 1年:3.65亿条 → 需要 62位(2^62 > 10^18)
- 存储:每条短链 500字节 → 3.65亿 × 500B ≈ 180GB/年
③ 核心设计:短链怎么生成?
方案A:哈希(MD5/SHA256)→ 冲突问题
方案B:自增ID转62进制 → 规律暴露,不安全
方案C:发号器(雪花算法)→ ✅ 推荐
雪花算法:1位符号 + 41位时间戳 + 10位机器ID + 12位序列号
→ 你简历里做过分布式系统,这个能讲
④ 存储设计
- 短链 → 长链 映射:Redis(热数据)+ MySQL(持久化)
- 表结构:(short_code PK, long_url, create_time, expire_time)
- 索引:short_code 唯一索引
⑤ 跳转优化
- 301 永久重定向(浏览器缓存,减轻服务器压力)
- 布隆过滤器:防止无效短链查库(缓存穿透)
⑥ 高可用
- 发号器多机部署,机器ID区分
- Redis 主从 + 哨兵
|
一句话总结
“短链系统核心是解决发号和映射两个问题。发号用雪花算法保证唯一,映射用 Redis + MySQL 分层,跳转用 301 缓存优化。”
二、设计消息队列(结合你 RAG 项目的 RabbitMQ 经验)
核心问题
实现一个类似 Kafka/RabbitMQ 的消息中间件
你的答题框架
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| ① 核心功能
- 生产者 → Broker → 消费者
- 支持 Topic/Queue 模型
- 消息持久化、ACK确认、重试机制
② 存储设计(最关键)
Kafka 做法:顺序写磁盘 + 零拷贝
- 每个 Topic 分 Partition
- 每个 Partition 是追加写的日志文件
- 索引文件(.index)加速定位
为什么磁盘比内存慢但 Kafka 很快?
→ 顺序写磁盘 ≈ 内存随机写,且 OS 会预读缓存
③ 你的经验可以套
你在 RAG 项目里用过 RabbitMQ:
- "我用 RabbitMQ 做了解耦,生产者解析文档入队,
消费者异步处理向量化"
- "我实现了手动 ACK + 消息不重复入队,异常时标记失败状态"
把这些迁移到设计题:
- "Broker 需要维护消费偏移量(offset),
消费者宕机后能从上次位置继续消费"
- "为了防止消息丢失,生产者需要收到 Broker 的 ACK 才认为发送成功"
④ 高可用
- 多副本机制(Leader-Follower)
- ISR(In-Sync Replicas)列表,只有同步完成的副本才算
|
一句话总结
“消息队列核心是顺序写磁盘保证吞吐,分区保证扩展,多副本保证可靠。我在 RAG 项目里用 RabbitMQ 实现了异步文档处理,理解了 ACK 和持久化的重要性。”
三、设计秒杀系统(结合你限流熔断的经验)
核心问题
100万人抢100个商品,怎么保证不超卖、不崩
你的答题框架
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| ① 核心挑战
- 瞬时高并发(QPS 100万+)
- 不能超卖(库存扣减一致性)
- 用户体验(不能卡顿/报错)
② 流量分层过滤(层层削峰)
浏览器 → CDN → Nginx → 网关 → 服务 → DB
- CDN:静态资源缓存,减少回源
- Nginx:限流(漏桶/令牌桶),你简历写过!
- 网关:鉴权 + 限流,无效请求直接拒
- 服务:库存预扣,异步下单
③ 库存扣减方案(防超卖)
❌ 直接查库:SELECT stock → UPDATE stock
并发下会超卖
✅ Redis 预扣 + Lua 脚本(原子操作)
EVAL "if redis.call('get', KEYS[1]) > 0 then
return redis.call('decr', KEYS[1])
else return -1 end" 1 stock:1001
✅ 数据库乐观锁
UPDATE stock SET count = count - 1
WHERE product_id = 1001 AND count > 0
④ 异步下单(削峰)
- 秒杀成功 → 发消息到 MQ → 异步创建订单
- 前端轮询或 WebSocket 推送结果
⑤ 你的经验可以套
你简历写了"令牌桶限流 + 状态机熔断":
- "我在 RPC 框架里实现了令牌桶限流,秒杀场景可以用
漏桶/令牌桶在网关层限流,保护后端"
- "熔断机制防止雪崩,如果库存服务挂了,快速失败"
|
一句话总结
“秒杀核心是层层限流削峰,Redis 原子扣库存防超卖,异步下单保证体验。我在 RPC 框架里实现的限流熔断策略可以直接复用。”
四、设计评论系统(结合你 MySQL 索引优化经验)
核心问题
微博/抖音的评论功能,支持分页、点赞、回复
你的答题框架
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| ① 数据模型
评论表 comments:
- id, content, user_id, post_id, parent_id(回复用), create_time
点赞表 likes:
- id, comment_id, user_id, create_time
② 分页查询优化(你简历写过慢 SQL 优化!)
❌ 深度分页:SELECT * FROM comments
WHERE post_id = 100 ORDER BY create_time
LIMIT 100000, 10
→ 扫描10万行,慢!
✅ 游标分页:SELECT * FROM comments
WHERE post_id = 100 AND create_time < '2024-01-01'
ORDER BY create_time DESC LIMIT 10
→ 走索引,快!
✅ 或者:SELECT * FROM comments WHERE id > 100000 LIMIT 10
③ 点赞计数
- 高频操作,不能每次查 COUNT(*)
- 方案:Redis 计数 + 定时回写 MySQL
- 或者:评论表冗余 like_count 字段,异步更新
④ 冷热数据分离
- 热评(最近7天):Redis 缓存
- 历史评论:MySQL 归档表
|
五、设计分布式 ID 生成器(最简单,先掌握)
核心问题
单机自增 ID 有瓶颈,分布式环境下怎么生成唯一 ID
你的答题框架
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| ① 方案对比
| 方案 | 优点 | 缺点 |
|------|------|------|
| UUID | 简单 | 无序、太长、不适合做索引 |
| 数据库自增 | 简单 | 单点、性能差 |
| 雪花算法 | 趋势递增、高性能 | 依赖时钟 |
| 号段模式(Leaf) | 数据库压力小 | 需要维护 |
② 雪花算法详解(重点讲这个)
64位 Long 型:
- 1位:符号位(0)
- 41位:时间戳(毫秒级,可用69年)
- 10位:机器ID(支持1024台机器)
- 12位:序列号(每毫秒4096个ID)
时钟回拨问题:
- 发生时等待或抛异常
- 或者记录上次时间戳,回拨时拒绝生成
③ 你的经验
你在 RPC 框架里做过服务注册发现:
- "机器ID可以通过 Nacos 动态分配,
或者启动时从配置中心获取"
|
总结
| 系统 | 核心知识点 | 你能套用的经验 |
|---|
| 短链 | 雪花算法、Redis 缓存 | 分布式系统经验 |
| 消息队列 | 顺序写磁盘、分区、副本 | RabbitMQ 使用经验 |
| 秒杀 | 限流削峰、Redis 原子操作 | 令牌桶限流、熔断 |
| 评论 | 分页优化、冷热分离 | 慢 SQL 优化经验 |
| 分布式 ID | 雪花算法 | 服务注册发现 |