rocketmq延迟消息实现原理

本文详细介绍了RocketMQ延迟消息的实现原理,包括producer发送请求、ScheduleMessageService的启动、commitLog和consumerQueue的区别以及延迟消息到期时间的设置。在broker启动时,18个timerTask负责检查延迟队列,确保消息按顺序有序处理。每个延迟级别对应一个topic和queue,当消息到期,它将被转换并投递到正确的位置。
摘要由CSDN通过智能技术生成

这篇笔记主要记录延迟队列的实现原理
总结来说:就是producer发送了一个请求之后,broker在收到请求时,会先判断当前请求中(消息中)的延迟级别是否不为null,不为null,就表示当前消息是延迟消息,就会根据程序员设置的延迟级别,将消息投递到指定的topic中,并且设置到期时间,在到期了之后,将消息从指定的topic中取出来,投递到真正程序员指定的topic和queue中

putMessage

putMessage方法是broker作为netty服务端,接收到producer的send请求之后,去处理消息的方法,在调用这个方法之前,还有多层的逻辑判断,暂时先不深究

org.apache.rocketmq.store.CommitLog#putMessage

if (msg.getDelayTimeLevel() > 0) {
    // 如果延迟级别超过最大级别,就设置延迟级别为18
    if (msg.getDelayTimeLevel() > this.defaultMessageStore.getScheduleMessageService().getMaxDelayLevel()) {
        msg.setDelayTimeLevel(this.defaultMessageStore.getScheduleMessageService().getMaxDelayLevel());
    }

    // 设置延迟消息的topic和queue
    topic = ScheduleMessageService.SCHEDULE_TOPIC;
    queueId = ScheduleMessageService.delayLevel2QueueId(msg.getDelayTimeLevel());

    // Backup real topic, queueId
    // 将真正的topic和queueId存起来,存到property属性中
    MessageAccessor.putProperty(msg, MessageConst.PROPERTY_REAL_TOPIC, msg.getTopic());
    MessageAccessor.putProperty(msg, MessageConst.PROPERTY_REAL_QUEUE_ID, String.valueOf(msg.getQueueId()));
    msg.setPropertiesString(MessageDecoder.messageProperties2String(msg.getProperties()));

    // 将消息的topic和queue替换为延迟队列的
    msg.setTopic(topic);
    msg.setQueueId(queueId);
}

ScheduleMessageService#start

这个类是处理延迟队里的关键类,是在broker启动的时候,会取启动这个异步线程,我们先看下异步线程中做的事情

/**
 * 在启动broker的时候,会初始化这里的timer
 * 并且会根据延迟级别,创建对应的timer任务
 */
public void start() {
    if (started.compareAndSet(false, true)) {
        this.timer = new Timer("ScheduleMessageTimerThread", true);
        // 这里for循环,会为每一个延迟级别创建一个延迟任务
        for (Map.Entry<Integer, Long> entry : this.delayLevelTable.entrySet()) {
            /**
             * level是设置的延迟级别
             */
            Integer level = entry.getKey();
            /**
             * value是延迟级别所对应的延迟时间
             * 以及对应的offset 偏移量?
             */
            Long timeDelay = entry.getValue();
            Long offset = this.offsetTable.get(level);
            if (null == offset) {
                offset = 0L;
            }

            // 初始化时,第一次延迟时间是1S,在后面任务执行之后(DeliverDelayedMessageTimerTask),会修改任务延迟时间
            if (timeDelay != null) {
                this.timer.schedule(new DeliverDelayedMessageTimerTask(level, offset), FIRST_DELAY_TIME);
           
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值