题目重点:Push、Email、SMS分别记录尝试,定义送达语义和去重范围。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练用户规模10^8+,渠道fallback、重试、延迟SLA由产品确定;没有默认“所有通知必须三个渠道全发”。
- provider接受≠用户看到。偏好/退订与通知优先级进入路由规则,不把营销和紧急通知套同一合同。
解题路线
- 事件表eventID/recipientID/payloadRef,delivery表(event,channel,attempt,status,providerID)。先outbox持久化再分发,按recipient分区使同用户顺序可控,批量fan-out和渠道worker解耦。
- 各provider有独立限速/重试/DLQ;超时UNKNOWN通过查询或带幂等键重试,不把timeout当确定失败。内部唯一(event,recipient,channel)防建重复delivery,但外部是否重复仍受provider能力限制。
- 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?
