如何实现Scheduled Notification服务,按用户偏好时间发送通知?
定时通知调度功能实现方案
你现有的即时通知发送逻辑不需要做大量改造,只需要新增调度层控制通知的触发时机即可,具体实现方案如下:
核心架构分层
整个定时通知服务可以拆为3个核心层:
- 存储层:存储用户的定时通知配置,核心字段包括用户ID、通知渠道、触发规则(可存cron表达式或者固定时间戳)、通知内容参数、执行状态、重试次数、用户时区
- 调度层:负责按照配置的时间规则触发通知执行,可根据业务规模选择不同的调度组件
- 执行层:直接复用你现有的通知发送逻辑,调度触发后调用对应发送接口即可,你当前的邮件发送代码如下:
String emailBody = "Hello,\n" + "\n" + "You have received a new notification " ; emailService.quickEmail(String.join(" ,", emailList), emailSubject, emailBody);
具体实现步骤
- 新增定时通知配置表,存储用户设置的偏好发送时间、通知内容、渠道等信息,每次用户新增/修改/删除定时通知时,同步更新配置表数据
- 接入调度组件,按固定频率(比如每分钟)拉取当前时间点需要触发的所有待执行通知:
拉取通知时需要先将对应记录的状态改为「执行中」,避免多实例并发拉取导致重复发送的问题
- 将拉取到的待发送通知丢到异步线程池执行,调用你现有的通知发送接口完成推送
- 执行完成后更新配置表记录的状态:发送成功标记为「已完成」,发送失败标记为「待重试」,单独运行重试任务处理失败的通知,超过最大重试次数标记为「发送失败」
- 如果你的用户分布在不同时区,存储触发时间时统一存UTC时间,调度时根据用户设置的时区换算为实际触发时间,避免时区偏差导致发送时间错误
不同业务规模的调度组件选型
- 单实例小流量场景(用户量<10万):直接使用Spring Boot自带的
@Scheduled注解即可,不需要额外引入中间件,开发成本最低 - 分布式多实例场景:选用XXL-Job、Elastic-Job等分布式调度框架,自带幂等、重试、任务分片、可视化管理能力,运维成本低
- 超大规模场景(用户量>千万):选用RocketMQ/Kafka的延迟消息能力,用户设置定时通知时直接投递对应延迟时间的消息,到时间后由消费者拉取执行发送,并发性能更高
定时通知调度参考流程:
内容的提问来源于stack exchange,提问作者Doyel Mishra
相关产品推荐
相关产品推荐

