1
skypyb 2019-12-05 11:01:55 +08:00
可以用时间轮
rabbitmq 消息 TTL+死信也可以啊。 |
2
wuzhizuiguo OP @skypyb 谢谢. rabbitmq 消息 TTL+死信队列 ,请问一下, 怎么实现 A 消息 10 秒过期, B 消息 5 秒过期, A 先进入队列, B 再进入, B 先出来发送邮件 . 博客上上说 , 队列进入时按照先入先出, 如果 B 过期了 还得等 A 过期了才会进入消费队列.
|
3
skypyb 2019-12-05 11:13:54 +08:00
@wuzhizuiguo rabbitmq 可以设置每条消息的过期时间。不过不叫 ttl,具体参数叫啥搜索引擎搜一下吧
|
4
wuzhizuiguo OP @skypyb 好的,谢谢. 是这个参数 message.getMessageProperties().setExpiration, 设置每条消息的过期时间. 现在如果每条消息设置同样的过期时间,A,B,C...都是 10 秒, 或者过期时间依次递增 10 秒,11 秒... 已经实现了. 会按过期时间顺序从死信队列里,然后进入 exchange 绑定的消费队列. 但是如果邮件发送时间 有 2 天后,1 天后,3 天后 这种 1 天后就得等 2 天后这条过期了,才会轮到它..
|
5
FaceBug 2019-12-05 11:33:23 +08:00
如果没有当天入洞,当天就要取出来的场景话,建议每天把次日的查出来,写到发送队列。
不同 mq 有不同的机制,如果 MQ 本身没有排序功能,可以用 redis 的 zset 先按秒排序,然后入队列,甚至直接用 redis 的 zset,每秒提取已经到期的消息发送。 |
6
wuzhizuiguo OP @cepczkd 谢谢. 如果没有当天写,当天就要发送的场景: 今天取出昨天的,查询排序,设置每条过期时间,写入延迟队列,发送,这个可行. 不过当天写 当天发送还是要有的..
redis zet 这个是有新提交的,就重新写入,然后根据 score 值排序, 获取需要发送的消息. 这个可以 |
7
mango88 2019-12-05 12:19:57 +08:00
|
9
wuzhizuiguo OP @mango88 谢谢. 这个好.如果安装了 就可以通过设置过期时间来实现了. (就是要安装插件..)
|
10
wuzhizuiguo OP 暂时准备用把数据放到 zset 和 mysql 里, spring boot 里 跑一个间隔 1 秒的定时器, 根据 score 值排序 把等于或小于当前时间的数据取出来发送,(再删除这些发送过的)
|
11
zhady009 2019-12-05 21:02:37 +08:00
redisson 有这种实现..还挺简单的 RScheduledExecutorService
不过还是得用 mysql 记录一下 taskId |
12
wuzhizuiguo OP |
13
star7th 2019-12-06 11:18:38 +08:00
两种方式都能做。用哪种方式都很轻松。第一种是起一个 cron 任务即可。用队列来做的话,利用我另一个开源项目 github.com/star7th/htq 里的定时任务特性就能做到。
|
14
zhady009 2019-12-06 12:17:13 +08:00
|
15
wuzhizuiguo OP @zhady009 好的,谢谢.我先用普通的定时器做做看,成功了再学下这个 redisson
|
16
wuzhizuiguo OP @star7th 好的,谢谢,就是看到了答主的时光树洞.
|
17
wuzhizuiguo OP 已经确认可以按照过期时间发送邮件. 用的是普通前端提交参数(假设,我不会前端, 用的 postman),后台 mysql 储存信息, 同时写入 redis 的 hash 表和 zset 中,设置 score 值为过期时间.接着 spring boot 启动一个定时器,@Scheduled, 设置为上一次结束到到上一次任务开始为 1 秒间隔. 在其中读取 zset 中 0~当前时间的元素(邮件 id), 再去 hash 中找到对应邮件 id 的邮件具体信息,然后删除对应的记录, 接着直接写入消息队列,然后从消息队列里出来, RPC 调用邮件发送接口, 这个地方如果量大了,可以用线程池来 RPC 调用,因为之前其他地方出现过 Hystrix 默认的线程数错误问题.
感谢各位大佬的热心解答,谢谢. |