如何设计通知系统:完整指南

发布: (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 或运营商网关实现全球覆盖。
  • 考虑运营商特定的限流和字符长度限制。

结论

设计通知系统需要在延迟、可靠性和成本之间取得平衡,同时支持多渠道并尊重用户偏好。通过将架构围绕稳健的事件流水线——生产者 → 中间件 → 工作者 → 渠道适配器——进行组织,可实现高可伸缩性、容错性和可观测性,使系统既适用于面试讨论,也能支撑真实生产工作负载。


参考文献

Back to Blog

相关文章

阅读更多 »