场景
设计一个消息推送系统,支持 iOS、Android 和 SMS 短信推送。
需求点:
- 支持多种推送类型:iOS Push、Android Push、SMS、Email。
- 软实时系统,希望用户尽快收到推送,但可以接受少量延迟。
- 支持 1000 万日活用户(DAU)。
- 用户可以选择退订推送。
估算
假设每个用户每天收到 10 条推送消息。
- 日推送量:10,000,000 × 10 = 1 亿条/天
- QPS:100,000,000 / 86400 ≈ 1157 次/秒
- 峰值 QPS:约 2300 次/秒
设计
整体架构
┌─────────────┐ ┌─────────────┐ ┌─────────────────┐
│ Service │────▶│ Message │────▶│ Push Workers │
│ Trigger │ │ Queue │ │ (iOS/Android) │
└─────────────┘ └─────────────┘ └─────────────────┘
│
▼
┌─────────────┐ ┌─────────────────┐
│ Device │◀────│ APNs/FCM/ │
│ Storage │ │ SMS Gateway │
└─────────────┘ └─────────────────┘
核心组件
推送服务入口
- 接收业务方的推送请求
- 参数校验、限流、鉴权
- 将消息写入消息队列
设备信息存储
- 存储用户设备 Token(APNs Token、FCM Token)
- 存储用户推送偏好设置
- 推荐使用 Redis + MySQL 组合
消息队列
- 解耦推送请求和实际发送
- 削峰填谷,应对流量突增
- 推荐使用 Kafka 或 RocketMQ
推送 Worker
- 消费消息队列中的推送任务
- 根据设备类型调用不同的推送通道
- 处理推送结果,记录失败重试
第三方推送通道
- iOS: APNs (Apple Push Notification service)
- Android: FCM (Firebase Cloud Messaging)
- SMS: 阿里云短信、腾讯云短信等
关键设计点
可靠性保证
- 消息持久化:推送消息入库后再发送
- 失败重试:指数退避重试机制
- 死信队列:多次重试失败的消息进入死信队列
去重机制
- 消息 ID 幂等性校验
- 短时间内相同内容去重
- 用户维度频率限制
用户偏好
- 支持用户退订特定类型推送
- 支持勿扰时段设置
- 推送频率限制
总结
| 组件 | 技术选型 |
|---|---|
| 消息队列 | Kafka / RocketMQ |
| 设备存储 | Redis + MySQL |
| iOS 推送 | APNs |
| Android 推送 | FCM |
| 短信推送 | 阿里云/腾讯云短信 |
核心挑战:
- 高可用:推送通道故障时的降级策略
- 实时性:控制端到端延迟
- 可观测:推送成功率、到达率监控
