方案一
由于RocketMQ只有固定的延时等级,如下:
public enum DelayTimeLevel {
NO_NEED_TO_DELAY(0, "无需延迟消费"),
ONE_SECOND(1, "1秒"),
FIVE_SECONDS(2, "5秒"),
TEN_SECONDS(3, "10秒"),
THIRTY_SECONDS(4, "30秒"),
ONE_MINUTE(5, "1分钟"),
TWO_MINUTES(6, "2分钟"),
THREE_MINUTES(7, "3分钟"),
FOUR_MINUTES(8, "4分钟"),
FIVE_MINUTES(9, "5分钟"),
SIX_MINUTES(10, "6分钟"),
SEVEN_MINUTES(11, "7分钟"),
EIGHT_MINUTES(12, "8分钟"),
NINE_MINUTES(13, "9分钟"),
TEN_MINUTES(14, "10分钟"),
ELEVEN_MINUTES(15, "11分钟"),
TWELVE_MINUTES(16, "12分钟"),
ONE_HOUR(17, "1小时"),
TWO_HOUR(18, "2小时");
}
任意时间的定时,使用RocketMQ本身是实现不了的,以下提供了通过借助RocketMQ实现任意时间的定时消息。
总体叙述:通过计算当前时间和定时的时间之间的秒数,去匹配RocketMQ的延时等级,如果没有匹配到,找到第一个比目前时间秒数小或者相等的级别,作为延时等级向MQ推送消息,以此类推,知道找到合适的延时等级。
算法图示
时间变化图示
优点:消息及时;
缺点:MQ里面有冗余的消息存在;
该方案具体的代码可以站内邮箱联系我。
方案二
通过定时任务去读取数据库,定时扫描,当扫描到满足推送的消息时,推送到MQ即可。
spring的定时任务,quartz定时任务。
优点:MQ不会存在冗余消息;
缺点:发送消息有延迟,取决于定时扫描的周期,太快了可能会影响性能,太慢了又不准时。