使用场景
工作中大家往往会遇到类似的场景:
1.对于红包场景,账户 A 对账户 B 发出红包通常在 1 天后会自动归还到原账户。
2.对于实时支付场景,如果账户 A 对商户 S 付款 100 元,5秒后没有收到支付方回调将自动取消订单。
解决方案分析
方案一:
采用通过定时任务采用数据库/非关系型数据库轮询方案。
优点:
1. 实现简单,对于项目前期这样是最容易的解决方案。
缺点:
1. DB 有效使用率低,需要将一部分的数据库的QPS分配给 JOB 的无效轮询。
2. 服务资源浪费,因为轮询需要对所有的数据做一次 SCAN 扫描 JOB 服务的资源开销很大。
方案二:
采用延迟队列:
优点:
1. 服务的资源使用率较高,能够精确的实现超时任务的执行。
2. 减少 DB 的查询次数,能够降低数据库的压力
缺点:
1. 对于延迟队列来说本身设计比较复杂,目前没有通用的比较好过的方案。
基于 Redis 的延迟队列实现
基于以上的分析,我决定通过 Redis 来实现分布式队列。
设计思路:
1. 第一步将需要发放的消息发送到延迟队列中。
2. 延迟队列将数据存入 Redis 的 ZSet 有序集合中score 为当前时间戳,member 存入需要发送的数据。
3. 添加一个 schedule 来进行对 Redis 有序队列的轮询。
4. 如果到达达到消息的执行时间,那么就进行业务的执行。
5. 如果没有达到消息的执行是将,那么消息等待下轮执行。
实现步骤:
由于本处篇幅有限,所以只列举部分代码,完整的代码可以在本文最后访问 GitHub 获取。由于本人阅历/水平有限,如有建议/或更正欢迎留言或提问。先在此谢谢大家驻足阅读