这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
完整架构
三个月后,通知系统长成了这样一张完整的架构图。它不再是某个脚本,而是由业务层、通知服务层、数据层和监控层组成的平台。
分层架构
┌─────────────────────────────────────────────────────────────────┐
│ 业务层 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 评论服务 │ │ 点赞服务 │ │ 关注服务 │ │ 私信服务 │ │
│ └─────┬────┘ └─────┬────┘ └─────┬────┘ └─────┬────┘ │
│ └──────────────┴──────────────┴──────────────┘ │
└──────────────────────────────┼───────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ 通知服务层 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 通知调度服务 │ │
│ │ - 接收业务事件 / 检查用户偏好 / 限流检查 / 消息聚合 │ │
│ └───────────────────────┬──────────────────────────────────┘ │
│ ┌───────────┴───────────┐ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ 推送服务 │ │ 站内信服务 │ │
│ │ - APNs/厂商推送 │ │ - 消息存储/查询 │ │
│ └──────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ MySQL │ │ Redis │ │ RabbitMQ │ │ ES │ │
│ │ 消息存储 │ │ 缓存/限流│ │ 消息队列 │ │ 日志搜索 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
各层职责
业务层
业务服务(评论、点赞、关注、私信)只做一件事:把”发生了什么”作为事件发出去,不关心通知怎么投递。这样业务逻辑和通知逻辑彻底解耦,新增业务只需要接入事件,不需要改动通知系统。
通知服务层
这一层是通知系统的核心,分成三块:
- 通知调度服务:接收业务事件,依次完成偏好检查、限流检查、消息聚合,然后决定是走推送还是站内信(或两者)。
- 推送服务:对接 APNs 和各安卓厂商推送,负责 token 管理、失败重试、静默推送和到达率监控。
- 站内信服务:负责消息持久化、已读/未读状态、多端同步和消息中心查询。
数据层
- MySQL(分表):站内信按用户 ID 分 16 张表,配合未读计数表和用户设备表。
- Redis:用户偏好缓存、未读计数、推送限流计数和分布式锁。
- RabbitMQ:异步削峰,把推送和站内信写入从业务链路中解耦出来。
- Elasticsearch:通知日志的搜索和分析。
监控层
Prometheus + Grafana 采集推送延迟、成功率、重复率、投诉率等指标,异常时触发告警。
一条通知的完整旅程
用户 A 评论了用户 B 的动态
↓
评论服务发出事件:comment.created
↓
RabbitMQ 接收事件(削峰)
↓
通知调度服务:
1. 查用户 B 的偏好(Redis)——是否接收评论通知?
2. 限流检查(Redis)——同一动态 1 小时内是否已发过?
3. 消息聚合——同一用户连续评论合并?
↓
命中投递策略:
站内信写入 MySQL 分表(记录已读/未读)
推送走 APNs/厂商推送(失败自动重试 3 次)
↓
用户 B 的 iPhone 收到推送,打开 App 看到站内信
其他设备通过静默推送同步未读状态
高可用设计
- 服务降级:推送服务不可用时,只发站内信,保证消息不丢。
- 消息重试:推送失败自动重试 3 次,配合死信队列兜底。
- 幂等处理:通知 ID + 消费记录,防止消息队列重复消费导致重复推送。
- 监控告警:延迟、成功率、投诉率超过阈值自动告警。
关键指标
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 推送延迟 | 5-10 秒 | < 1 秒 |
| 推送成功率 | 85% | 95% |
| 重复推送率 | 5% | < 0.1% |
| 系统可用性 | 95% | 99.9% |
这套架构的关键不在于用了多少中间件,而在于每一层都只解决一类问题:业务层产生事实,调度层做决策,投递层保证触达,数据层负责存储,监控层让一切可观测。
