定时推送日程消息的实现预研

定时推送日程消息的实现预研

1.定时任务:可以实现,但比较消耗资源

2.使用rocketmq的延时队列 实现代码的示例如下

(1)实现方式1

是的,RocketMQ也可以实现类似的延迟消息功能。下面是一个使用RocketMQ消息队列实现日程提醒功能的示例代码: 1. 创建日程时,将其存储在数据库中,并将其对应的提醒时间发送到消息队列中。

@Service
public class ScheduleService {

  @Autowired
  private RocketMQTemplate rocketMQTemplate;

  @Autowired
  private ScheduleRepository scheduleRepository;

  public void createSchedule(Schedule schedule) {
    scheduleRepository.save(schedule);
    LocalDateTime remindTime = schedule.getScheduleTime().minusMinutes(15);
    Message> message = MessageBuilder.withPayload(schedule.getId())
        .setDelayTimeLevel(4) // 设置延迟级别,对应15分钟
        .build();
    rocketMQTemplate.syncSend("schedule-remind-topic", message);
  }
}

在上面的代码中,我们在创建日程时,将其存储在数据库中,并将其对应的提醒时间发送到RocketMQ消息队列中。我们使用RocketMQTemplate发送消息,将日程ID作为消息体,发送到名为schedule-remind-topic的主题中。我们还使用setDelayTimeLevel()方法设置消息的延迟级别,对应15分钟的延迟时间。 2. 在消费者中,监听消息队列,当有消息到达时,进行提醒操作。

@Component
public class ScheduleRemindConsumer implements RocketMQListener> {

  @Autowired
  private ScheduleService scheduleService;

  @Autowired
  private ReminderService reminderService;

  @Override
  public void onMessage(Long scheduleId) {
    Schedule schedule = scheduleService.getSchedule(scheduleId);
    reminderService.sendReminder(schedule);
  }
}

在上面的代码中,我们实现了RocketMQListener接口,用于监听名为schedule-remind-topic的主题。当有消息到达时,调用onMessage()方法进行处理。该方法会获取对应的日程,并调用reminderService.sendReminder()方法发送提醒。 请注意,上述代码中的ScheduleServiceReminderService是您需要自己实现的服务类,用于获取日程和发送提醒。您需要根据自己的业务逻辑实现这些服务。另外,上述代码中使用的是RocketMQ消息队列,您也可以使用其他消息队列实现类似的功能。

(2)实现方式2

下面是一段示例代码,演示如何在消费者端实现自定义延时消费:

public class DelayConsumer implements MessageListenerConcurrently {
    private static final String DELAY_TOPIC = "delay_topic";
    private static final String DELAY_TAG = "delay_tag";
    private static final String DELAY_QUEUE = "delay_queue";
    private static final String GROUP_ID = "delay_consumer_group";

    private DefaultMQPushConsumer consumer;

    public DelayConsumer() throws MQClientException {
        consumer = new DefaultMQPushConsumer(GROUP_ID);
        consumer.setNamesrvAddr("localhost:9876");
        consumer.subscribe(DELAY_TOPIC, DELAY_TAG);
        consumer.registerMessageListener(this);
        consumer.start();
    }

    @Override
    public ConsumeConcurrentlyStatus consumeMessage(ListExt> msgs, ConsumeConcurrentlyContext context) {
        for (MessageExt msg : msgs) {
            if (msg.getTopic().equals(DELAY_TOPIC) && msg.getTags().equals(DELAY_TAG)) {
                long delayTime = Long.parseLong(msg.getUserProperty("delayTime"));
                if (System.currentTimeMillis() - msg.getStoreTimestamp() >= delayTime) {
                    // 处理消息
                    System.out.println(new String(msg.getBody()));
                } else {
                    // 将消息放入延时队列
                    try {
                        Message newMsg = new Message(DELAY_TOPIC, DELAY_TAG, msg.getBody());
                        newMsg.setDelayTimeLevel(0); // 设置延迟级别为1秒
                        SendResult result = consumer.getDefaultMQProducer().send(newMsg);
                        System.out.println("Message " + result.getMsgId() + " sent to delay queue.");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }

    public static void main(String[] args) throws MQClientException {
        new DelayConsumer();
    }
}

在这个示例中,我们使用RocketMQ的PushConsumer来消费消息,当消费到需要延时消费的消息时,我们首先判断消息是否已经到达可消费状态,如果是,则直接进行消息处理;否则,将消息放入延时队列中,等待指定时间后再进行消费。这里我们使用RocketMQ的生产者来将消息放入延时队列中,需要注意的是,生产者和消费者必须使用相同的Namesrv地址。

(3)实现方式3

下面是一个使用 RocketMQ 实现定时关闭订单功能的示例代码: 1. 首先,在 pom.xml 文件中添加 RocketMQ 的依赖:

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>

\2. 在 application.properties 文件中配置 RocketMQ 的相关参数:

# NameServer 地址
rocketmq.name-server=127.0.0.1:9876
# 生产者组名
rocketmq.producer.group=orderProducerGroup
# 消费者组名
rocketmq.consumer.group=orderConsumerGroup
# 主题名
rocketmq.topic=orderTopic
# 订单关闭消息的标签
rocketmq.tag=orderClose

\3. 创建一个 RocketMQ 的生产者,用于发送订单关闭消息:

@Component
public class OrderProducer {
    
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    
    @Value("${rocketmq.topic}")
    private String topic;
    
    @Value("${rocketmq.tag}")
    private String tag;
    
    public void sendOrderCloseMessage(String orderId, long delayTime) {
        Message> message = MessageBuilder.withPayload(orderId)
                .setHeader(MessageConst.PROPERTY_DELAY_TIME_LEVEL, String.valueOf(delayTime))
                .build();
        rocketMQTemplate.syncSend(topic + ":" + tag, message);
    }
}

这个示例代码中,我们注入了 RocketMQTemplate,用于发送消息。在 sendOrderCloseMessage() 方法中,我们创建了一个消息,设置了消息体为订单号,并设置了延时时间。然后,我们使用 rocketMQTemplate 发送消息。 4. 创建一个 RocketMQ 的消费者,用于接收订单关闭消息:

@Component
public class OrderConsumer implements RocketMQListener> {
    
    @Value("${rocketmq.topic}")
    private String topic;
    
    @Value("${rocketmq.tag}")
    private String tag;
    
    @Override
    public void onMessage(String orderId) {
        // 关闭订单的逻辑
    }
    
    @PostConstruct
    public void subscribe() {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer();
        consumer.setConsumerGroup("orderConsumerGroup");
        consumer.setNamesrvAddr("127.0.0.1:9876");
        try {
            consumer.subscribe(topic, tag);
            consumer.registerMessageListener(this);
            consumer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }
    }
}

这个示例代码中,我们实现了 RocketMQListener 接口,并重写了 onMessage() 方法,用于处理接收到的消息。在 subscribe() 方法中,我们创建了一个 Push 消费者,并订阅了指定的主题和标签,注册了消息监听器,并启动了消费者。 5. 在需要关闭订单的地方,调用 OrderProducersendOrderCloseMessage() 方法发送订单关闭消息,例如:

@Autowired
private OrderProducer orderProducer;

public void closeOrder(String orderId, long delayTime) {
    orderProducer.sendOrderCloseMessage(orderId, delayTime);
}

这个示例代码中,我们调用 OrderProducersendOrderCloseMessage() 方法,发送一个订单关闭消息,并设置延时时间。 这样,我们就完成了使用 RocketMQ 实现定时关闭订单功能的示例代码。

备注:rocketmq的延时级别

RocketMQ的延迟级别是通过设置消息的延迟级别属性来实现的,它可以控制消息在发送后多久被消费者接收。RocketMQ支持18个延迟级别,分别为1秒、5秒、10秒、30秒、1分钟、2分钟、3分钟、4分钟、5分钟、6分钟、7分钟、8分钟、9分钟、10分钟、20分钟、30分钟、1小时、2小时和3小时。在发送消息时,可以通过设置消息的延迟级别属性来指定消息的延迟时间,RocketMQ会根据延迟级别来计算消息的实际延迟时间。

3.使用redis的特殊数据结构,实现类似消息队列的效果

4.使用redission的过期回调,实现回调后推送消息

如果需要在key过期时执行回调函数,可以使用一些工具或框架来实现,比如使用Redisson框架,它提供了一些功能来实现类似于Redis的key过期回调函数的功能。Redisson提供了一个RMapCache对象,它可以像普通的Map一样存储键值对,并且可以设置每个键的过期时间。当键过期时,Redisson会触发回调函数来执行相关的逻辑。 以下是一个使用Redisson实现key过期回调函数的示例代码:

import org.redisson.Redisson;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

public class RedissonDelayCloseExample {

    public static void main(String[] args) {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://localhost:6379").setDatabase(0);

        RedissonClient redisson = Redisson.create(config);

        RMapCache, String> map = redisson.getMapCache("myMap");
        map.addListener((key) -> {
            // 在这里处理相关逻辑
            System.out.println(String.format("Key %s has expired and is being processed.", key));
        });
        map.put("key1", "value1", 5); // 设置带有过期时间的键

        redisson.shutdown();
    }

}

在上面的代码中,我们使用了Redisson框架来实现key过期回调函数的功能。我们使用Config对象来配置Redis连接信息,然后使用Redisson.create方法创建RedissonClient对象。我们使用RMapCache对象来存储键值对,并且设置了一个回调函数,当键过期时,Redisson会触发回调函数来执行相关的逻辑。在主函数中,我们设置带有过期时间的键,然后等待键过期时触发回调函数执行相关逻辑。最后,我们使用redisson.shutdown方法关闭RedissonClient对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值