如何设计通知系统:完整指南
发布: (2025年12月7日 GMT+8 00:36)
7 min read
原文: Dev.to
Source: Dev.to
介绍
本指南概述了如何构建一个可伸缩的通知服务,支持邮件、短信、推送和应用内渠道。内容涵盖用户偏好、限流、同步与批量投递、带重试的队列、高可用性,以及延迟、成本和可靠性之间的权衡。
通知类型与使用场景
- 推送通知 – 通过 FCM 或 APNs 等服务向移动端和桌面端发送提醒。(Firebase)
- 邮件通知 – 交易类邮件,如密码重置、收据或促销信息。(SendGrid)
- 短信通知 – 对时间敏感的提醒,如一次性密码(OTP)或配送更新。(Twilio)
- 应用内通知 – 在应用内部显示的提醒,通常使用 WebSocket 等实时连接。
典型场景
- 用户参与(鼓励回访)
- 交易更新(付款、订单、配送)
- 安全警报(登录提醒、密码变更)
- 系统通知(停机、维护、功能变更)
核心需求
| 需求 | 描述 |
|---|---|
| 多渠道支持 | 推送、短信、邮件和应用内提醒 |
| 可靠投递 | 通过重试确保发送成功 |
| 用户偏好 | 静音时段、首选渠道、退订选项 |
| 个性化 | 上下文感知的消息(例如 “Hi John,您的包裹已在路上”) |
| 重试机制 | 失败后带退避的重新发送 |
| 可伸缩性 | 每分钟数百万条通知 |
| 低延迟 | OTP、安保提醒等需要秒级投递 |
| 高可用性 | 在故障情况下仍能运行 |
| 容错性 | 恢复时不丢失数据 |
| 可观测性 | 用于投递状态的指标、日志、追踪 |
挑战
- 高并发 – 在短时间内交付海量请求。
- 渠道复杂度 – 每个渠道都有各自的故障模式和限制。
- 投递保证 – 在至多一次、至少一次或恰好一次语义之间做选择。
- 大规模用户偏好 – 高效执行用户的订阅/退订和静音时段。
- 故障处理 – 重试、指数退避、死信队列以及外部服务的回退方案。
高层架构
[Producers] → [Ingress API] → [Message Broker] → [Worker Pool] → [Channel Adapters] → External Providers
组件
生产者(事件源)
生成通知事件(例如订单已下、收到消息、系统警报)。
消息中间件 / 队列
在生产者和工作者之间充当缓冲。常见选型:
- Apache Kafka – 高吞吐、可回放、分区。(Apache Kafka)
- RabbitMQ – 灵活路由,适合复杂模式。
- AWS SQS / Google Pub/Sub – 完全托管,运维负担低。(DataCamp)
通知服务(工作者)
- 从队列读取事件。
- 应用业务逻辑并检查用户偏好。
- 选择合适的渠道。
- 为每个渠道格式化负载。
渠道集成
- 推送 – APNs / FCM 适配器。
- 邮件 – SMTP、SendGrid 或 Amazon SES。
- 短信 – Twilio 或运营商网关。(Twilio)
数据库
存储:
- 用户偏好和设备令牌。
- 投递日志、限流信息和通知历史。
- 用于恰好一次处理的幂等键。
监控与日志
收集指标、仪表盘和追踪数据,以监控投递成功、失败以及重试次数。
事件负载示例
{
"event_id": "uuid-v4",
"event_type": "ORDER_SHIPPED",
"priority": "MEDIUM",
"user_id": "user-123",
"tenant_id": "org-456",
"timestamp": "2025-12-06T12:34:56Z",
"payload": {
"order_id": "order-789",
"tracking_url": "https://carrier/track/..."
},
"channels": ["PUSH", "EMAIL"], // optional override
"idempotency_key": "user-123-order-789"
}
- 队列 将生产者与消费者解耦,提供缓冲并实现背压。
- 分区键(例如
user_id % partitions)有助于在保持必要的用户顺序时分散负载。 - 死信队列(DLQ) 捕获多次重试仍失败的事件。
选型对比
| 队列 | 优势 | 典型使用场景 |
|---|---|---|
| Apache Kafka | 超高吞吐、持久日志、可回放 | 大流量流式处理管道 |
| RabbitMQ | 丰富路由、确认机制 | 复杂路由、适中规模 |
| AWS SQS / Pub/Sub | 托管服务、操作简便 | 需要最小运维开销的场景 |
渠道集成细节
推送通知
- 使用 FCM 进行 Android 与跨平台投递;可代理至 APNs 发送 iOS。
- 存储设备令牌,处理失效并轮换陈旧令牌。
- 注意负载大小限制,保持消息简洁。
邮件通知
- 优先使用事务型提供商(SendGrid、Amazon SES)以提升送达率和信誉。
- 实现限流和退避,避免被 throttling。
短信通知
- 使用 Twilio 或运营商网关实现全球覆盖。
- 考虑运营商特定的限流和字符长度限制。
结论
设计通知系统需要在延迟、可靠性和成本之间取得平衡,同时支持多渠道并尊重用户偏好。通过将架构围绕稳健的事件流水线——生产者 → 中间件 → 工作者 → 渠道适配器——进行组织,可实现高可伸缩性、容错性和可观测性,使系统既适用于面试讨论,也能支撑真实生产工作负载。