Skip to content

第 10 章:设计通知系统

简介

通知系统为现代应用提供及时的商品动态、活动、优惠和告警等信息。通知渠道包括:

  1. 推送通知(移动设备或桌面端);
  2. 短信
  3. 电子邮件

本章重点设计每天能够发送数百万条通知的可扩展系统。


第一步:理解问题

需求

  • **通知类型:**推送通知、短信和电子邮件。
  • **送达时效:**软实时,尽量减少延迟。
  • **平台:**iOS、Android 和桌面端。
  • **触发方式:**可由客户端应用触发,也可在服务端定时触发。
  • 规模:
    • **推送通知:**每天 1000 万条;
    • **短信:**每天 100 万条;
    • **电子邮件:**每天 500 万封。
  • **退订支持:**用户可以关闭特定类型的通知。

第二步:概要设计

组件

  1. 通知渠道:

    • **iOS 推送:**使用 Apple Push Notification Service(APNS)
    • **Android 推送:**使用 Firebase Cloud Messaging(FCM)
    • **短信:**使用 Twilio 或 Nexmo 等第三方服务。
    • **电子邮件:**使用 SendGrid 或 Mailchimp 等商业邮件服务。
  2. 收集联系方式:

    收集联系方式
    • 在安装应用或注册时收集设备令牌、电话号码和邮箱地址。
    • 将联系方式存入数据库:
      • **设备令牌表:**用于推送通知。
      • **用户表:**用于邮箱地址和电话号码。
  3. 通知发送流程:

    概要设计
    • 触发服务:
      • 产生通知事件,如账单提醒和物流更新。
      • 可以是微服务、定时任务或分布式系统。
    • 通知服务器:
      • 提供发送通知的 API。
      • 对邮箱地址和电话号码进行基本校验。
      • 从数据库或缓存获取渲染通知所需的数据。
    • **第三方服务:**将通知送达用户。

初始设计的挑战

  • **单点故障(SPOF):**唯一的通知服务器一旦故障,整个系统就会瘫痪。
  • **扩容困难:**数据库、缓存和处理组件难以独立扩容。
  • **性能瓶颈:**发送通知需要大量资源。

改进设计

  <img src="/images/chapter-10/improved-design.png" alt="改进设计" width="500" />
  • 将数据库和缓存从通知服务器中独立出来。
  • 部署多台通知服务器,实现水平扩容
  • 使用消息队列解耦组件,并在通知量激增时提供缓冲。
  • 增加工作进程,从队列中取出通知事件,交给对应的第三方服务发送。

第三步:详细设计

可靠性

  1. 防止数据丢失:

    数据丢失
    • 将通知数据持久化到数据库,并实现重试机制。
    • 通知日志数据库用于保存通知记录。
  2. 去重:

    • 检查事件 ID,避免重复发送通知。
    • 通知事件到达时,先根据事件 ID 判断是否处理过;处理过则丢弃,否则发送。

补充组件

事件追踪
  1. **通知模板:**预定义格式,保证通知一致性并提高生成效率。
  2. 通知设置:
    • 用户可以分别订阅或退订推送、短信和邮件。
    • 设置保存在专门的通知设置表中。
  3. **限流:**限制向同一用户发送通知的频率。
  4. **重试机制:**第三方服务发送失败时重新尝试。
  5. **队列监控:**跟踪积压量,以便动态扩展工作进程。
  6. **事件追踪:**收集打开率、点击率和参与度等指标。

安全性

  • 使用 AppKeyAppSecret 验证推送通知 API 请求。

通知流程

更新后的设计
  1. 触发服务调用 API 请求发送通知。
  2. 通知服务器验证请求,并从缓存或数据库读取元数据。
  3. 通知事件进入消息队列。
  4. 工作进程处理事件,并调用第三方服务。
  5. 第三方服务将通知送达用户。

关键优化

  1. **水平扩容:**增加通知服务器以分担负载。
  2. **消息队列:**解耦处理流程,承受大量通知。
  3. **缓存:**缓存常用数据以降低延迟。
  4. **地理分布式处理:**按地理位置优化消息投递,提高性能。