RocketMq comsumer源码

消费者启动

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

消息拉取

集群模式:各个消费者通过负载均衡的方式消费消息
广播模式:每一个消费者消费所有消息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

消息队列负载与重新分布机制

在这里插入图片描述
在这里插入图片描述

消息消费过程

PullMessageService负责对消息队列进行消息拉取,从远端服务器拉取消息后将消息存储ProcessQueue消息队列处理队列中,然后调用ConsumeMessageService#submitConsumeRequest方法进行消息消费,使用线程池来消费消息,确保了消息拉取与消息消费的解耦。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

消息发送时数据在ConsumeQueue的落地

在这里插入图片描述
连续发送5条消息,消息是不定长,首先所有信息先放入 Commitlog中,每一条消息放入Commitlog的时候都需要上锁,确保顺序的写入。
当Commitlog写成功了之后。数据通过ReputMessageService类定时同步到ConsunmeQueue中,写入Consume Queue的内容是定长的,固定是20个Bytes(offset 8个、size 4个、Hashcode of Tag 8个)。

查找消息的时候,可以直按根据队列的消息序号,计算出索引的全局位置(比如序号2,就知道偏移量是20),然后直接读取这条索引,再根据索引中记录的消息的全局位置,找到消息。这两次查找是差不多的:第一次在通过序号在consumer Queue中获取数据的时间复杂度是O(1),第二次查找commitlog文件的时间复杂度也是O(1),所以消费时查找数据的时间复杂度也是O(1)。

消息消费参考:https://blog.csdn.net/yuanshangshenghuo/article/details/110494587

messagequeue和processqueue的区别

MessageQueue 和 ProcessQueue 是 RocketMQ 中的两个重要概念,它们在消息处理过程中起着不同的作用。
MessageQueue:这是 RocketMQ 的基本组成部分,用于表示拉取回来的消息元数据信息,包括 topic、brokerName、queueId 等。MessageQueue 是 RocketMQ 消息收发模型中的一个组成部分,虽然所有的消息资源以主题粒度管理,但实际的操作实现是面向 MessageQueue。
ProcessQueue:这是 RocketMQ 客户端用于处理消息的一个重要组件。ProcessQueue 是 MessageQueue 的消费快照。消息拉取的时候,会将实际消息体、拉取相关的操作存放在其中。比如消费进度,消费等等功能的底层核心数据保存都是有 ProcessQueue 提供。ProcessQueue 中包含了一些重要的成员变量,如 msgTreeMap(临时存放消息用的),msgCount(消息总数量),msgSize(整个 ProcessQueue 处理单元的总消息长度)等。

消息消费时,messagequeue锁的意义和processqueue锁的意义

在 RocketMQ 中,MessageQueue 锁和 ProcessQueue 锁在消息消费时起着不同的作用。

MessageQueue 锁:这是一个全局锁,用于在 ConsumeMessageOrderlyService 中对整个 MessageQueue 进行加锁。这样做的目的是保证同一时刻只有一个线程对 MessageQueue 进行处理。这个锁是在 ConsumeRequest.run() 方法中实现的。如果获取到这个 messageQueue 的锁,则进行消息消费;如果没有获取到锁,把该请求重新放到线程池中,该线程不会阻塞,可以继续处理线程池中的其他请求。另外,这个锁还有另一个作用,那就是防止在当前消费者还在消费,且没有提交位移时发生了重平衡,正在消费的 messagequeue 被分配给了其他消费者,导致重复消费。
ProcessQueue 锁:这是一个队列级别的锁,用于保证在处理单个队列中的消息时的线程安全。当拿到锁的线程从 ProcessQueue 拿出消息时,是按照 offset 顺序拿的,从而保证按顺序处理消息。如果业务处理失败,会把当前处理的消息重新放回 ProcessQueue 中,当前线程直接结束,后续重新启动线程对消息进行处理。所以即使业务处理失败,也能保证按消息的顺序进行处理。

消息消费为什么要对message加锁

在 RocketMQ 中,对 MessageQueue 加锁的主要目的是为了保证消息消费的有序性。这是因为 RocketMQ 支持顺序消息消费,即消息需要按照发送的顺序进行消费。

当 MessageQueue 的队列个数小于消费组中消费者的个数时,如果不加锁,可能会导致多个消费者消费同一个队列,存在竞争。但是,通过查看 AllocateMessageQueueStrategy 的实现源码,发现当 MessageQueue 的队列个数小于消费组中消费者的个数时,会导致超出个数的消费者无队列可消费,即负载不均衡,但并不会出现多个消费者争抢消费同一个消费队列的情况。

另外,MessageQueue 的锁还有另一个作用,那就是防止在当前消费者还在消费,且没有提交位移时发生了重平衡,正在消费的 messagequeue 被分配给了其他消费者,导致重复消费。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值