SWE · System Design

亿级用户全球通知:事件、渠道投递与Fallback

Push、Email、SMS分别记录尝试,定义送达语义和去重范围。

题目重点:Push、Email、SMS分别记录尝试,定义送达语义和去重范围。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练用户规模10^8+,渠道fallback、重试、延迟SLA由产品确定;没有默认“所有通知必须三个渠道全发”。
  • provider接受≠用户看到。偏好/退订与通知优先级进入路由规则,不把营销和紧急通知套同一合同。

解题路线

  1. 事件表eventID/recipientID/payloadRef,delivery表(event,channel,attempt,status,providerID)。先outbox持久化再分发,按recipient分区使同用户顺序可控,批量fan-out和渠道worker解耦。
  2. 各provider有独立限速/重试/DLQ;超时UNKNOWN通过查询或带幂等键重试,不把timeout当确定失败。内部唯一(event,recipient,channel)防建重复delivery,但外部是否重复仍受provider能力限制。
  3. fallback规定触发条件:push明确失败/超过期限且未确认,再CAS切换email;迟到push可能同时到达,要接受业务允许的跨渠道重复或用可撤销渠道/确认窗口。不存在一般跨多个provider端到端exactly-once保证。

手动走一遍

一事件发100万用户,先写事件和fanout批次cursor,再批量delivery,worker故障从cursor继续,不重新全量发送。SMS超时后转Email,SMS稍后成功会双渠道送达;方案应事先说明是否接受及如何展示同notificationID。

规模与取舍

若10^8用户每日5次,平均约5787个recipient事件/秒,峰值倍率与平均渠道尝试数再乘。保存D天delivery量约5×10^8×D×尝试数,需分区保留与payload去重。

易错点与追问

容易失分的边界

  • provider回执乱序不能让delivered退回pending。
  • 退订后队列里旧营销消息仍发,应在投递前检查必要的最新偏好。

继续深挖

  • 通知内容变更/撤回如何在各渠道能力不同情况下定义?
  • 多region灾备怎样迁移分区owner且防重复fanout?
✓已复制微信号!