Yihui’s Blog

500 万会员即将过期,如何提前 7 天提醒?

日期:2026-07-11
标签:#面试 #八股 #后端 #定时任务 #消息通知 #场景题

一句话答案

对过期时间建立索引,按固定时间窗口和主键游标分批扫描“7 天后到期”会员,生成唯一提醒任务并异步发送,延迟队列可做实时调度,定时扫描负责兜底。

面试口语版

500 万并不需要每天全表扫描。会员表对 expire_time 建索引,每天按业务时区查询 [今天+7天, 明天+7天) 的记录,并按主键游标分批提交到 MQ。提醒表以 memberId + expireTime + remindType 建唯一键,防止任务重跑造成重复通知;消费者按短信、Push、站内信分别限流、重试和记录结果。如果续费改变到期时间,旧提醒任务在发送前再次校验当前 expireTime。时间轮或延迟队列可以降低扫描延迟,但数据库窗口扫描和对账仍是可靠兜底。

关键细节

  • 明确时区、自然日和“提前 7×24 小时”语义。
  • 不使用大 Offset,按 (expire_time,id) 游标分页。
  • 发送前检查用户订阅、免打扰和最新会员状态。
  • 渠道失败分类重试,并控制供应商速率和成本。

面试官追问

  1. 定时任务执行两次如何避免重复提醒?
  2. 用户在提醒前续费了怎么办?
  3. 多实例如何并行扫描?

面试官追问参考答案

1. 定时任务执行两次如何避免重复提醒?

提醒任务表对会员、目标到期时间和提醒类型建立唯一约束,重复扫描只能插入一条任务;消费者再按 taskId 幂等发送。分布式任务锁只能减少重复执行,唯一约束才是最终防线。

2. 用户在提醒前续费了怎么办?

任务记录生成时的 expireTime,发送前重新读取会员状态;若当前过期时间已变化或不再符合 7 天窗口,则取消旧任务。续费事件也可以主动撤销未发送提醒。

3. 多实例如何并行扫描?

按主键哈希、会员分区或过期时间子区间分片,每个实例领取任务分片并记录 checkpoint。分片租约过期可由其他实例接管,所有插入仍依赖唯一键幂等。

学习清单

  • 掌握时间窗口索引扫描和幂等提醒表。
  • 能处理续费变更、重试和多实例分片。
维护与整理 · Yihui在 GitHub 上编辑

继续阅读

浏览全部文章