背景
最近有些空余时间,刚好看下Rocketmq4.8.0处理逻辑(5.0架构改造很大,暂时没投入使用,就不先看了)
Rebalance机制处理流程图

细节点
细节点
- 并发消费是直接投入到线程池中进行消费的,顺序消费则是通过synchronized锁住整个队列来控制单个顺序消费
- 广播消费模式偏移量等都是自己消费组控制的,不需要几种管理,所以逻辑上相对简单挺多
- 消费者推拉模式,实际上都是拉,只是一种是rocketmq帮你取拉,一种是自己硬编码去拉
- 为什么顺序消费重负载需要去申请broker锁呢?因为为了保证真实的顺序消费,必须中心化管理这个队列,而broker就刚好是这样的
- 为什么顺序消费的时候要设置一个消费锁,实际上不都是单线程消费吗?我理解可以去除也没问题,后续是chatgpt答案:虽然在某些情况下,去掉本地锁可能不会立即出现问题,但在高并发场景下,多个线程同时访问共享资源的概率会增加,这时候就更容易出现线程安全问题。因此,为了保证系统的稳定性和数据的一致性,使用本地锁是一个良好的编程实践。
- 为什么使用TreeMap来存储消息
- 数据自动排序:TreeMap 能够自动对键值进行排序,可以保证消息按照 offset 的顺序进行存储和消费;
- 快速查找:由于 TreeMap 是基于红黑树实现的,因此查找效率很高,可以快速定位消息;
- 内存占用低:与 HashTable 或 ConcurrentHashMap 相比,TreeMap 的内存占用要低一些,因为它不需要额外的空间来维护哈希表;
- 线程安全:TreeMap 是线程安全的,可以在多线程环境下安全地进行操作。
- 因为查询/增/删/改/时间查询复杂度O(logN),所以可以用跳表来?
- TreeMap时机
- 拉取消息成功 (putMessage)
- 并发消费,长时间不消费的消息清理(cleanExpiredMsg)
- 主动删除消息,消息消费成功后操作(removeMessage)
- 还有些杂七杂八的自己看把
- 消息重试逻辑,消费失败->重新丢回broker队列中,其中topic=SCHEDULE_TOPIC_XXXX(对应18个队列),如果丢回失败,就本地重试→每个队列有时间,时间到了,重新丢回topic=%RETRY%+消费组名
- 并发消费偏移量管理
- 如果 1 - 10
- 其中除了2没有消费完全,那么此时消费偏移量就是2,这时候重启的话,2-10又会重新消费,这也是rocketmq要求我们做到幂等一个问题
- 增加分区,会触发rebalance,有时候好的方式解决吗,暂时没有
- 顺序消费锁
- broker锁,确定这个队列只分配给某个节点
- messageQueue锁,确定这个队列只能有一个消费线程处理
- processQueue锁,确保rebalance能不重复消费
Rocketmq文件存储机制


网图截图
- commitlog(消息内容)
- 文件存储机制:所有主题消息都是顺序写入的
- 1GB一个文件,超出后提前生成
- 回收机制,定期回收,因为该文件机制,所以只能全局设置回收机制,不能类似kafka进行单个topic进行设置回收时间
- consumerQueue(消费队列)
- 多个主题以及多个队列偏移量管理
- 消息格式
- 消息偏移量:该消息在commitlog文件中的偏移量看,占用8字节64位,能够唯一标识该消息在commitlog中的位置
- 消息大小:4个字节,标识消息大小
- 消息hashcode值:8位。消息tag过滤是consumer申请拉取消息时候,broker按照主题方式去获取消息,通过hashcode去对比下是不是满足要求,返回给消费者,消费者拿到该消息在和topic信息对比,如果不满足就丢弃。
- indexfile(索引文件)
- 根据消息的key构建的索引文件
- 消息格式
- IndexHeader:文件头部,包含了文件的基本元信息和全局配置数据。
- Slot:一系列的槽位,每个槽位通常占4个字节,用于快速定位索引项在文件中的位置,RocketMQ默认提供了约500万个槽位来分散Hash冲突。
- Index Entry:实际的索引条目,包含了与消息关联的Key和其他元数据,以及消息在CommitLog中的偏移量。理解,其实就是压缩列表存储,但是其中肯定是有冲突的,直接在Index Entry构建一个链表即可
- Broker机制
- 刷盘机制:
- 同步
- 异步
- 同步机制:
- 主从同步
- 4.5之前都是需要人为手动切换,只是提供了主从数据同步机制,并没有HA机制进行切换,4.5后采用Dledger机制进行HA处理,其中涉及raft算法
- 零拷贝
- 基于mmap+write实现的零拷贝,减少了用户态和内核态数据拷贝问题,同时提供内存映射读取,增强性能
- 区别于kafka的零拷贝机制,kafka使用mmap进行消息写入,在使用sendfile进行消息读取
- 堆外内存配置
- 正常流程write pagecache→flush disk
- 开启后writr DirectByteBuffer → sync pagecache → flush disk
- 优点
- 提高系统吞吐量,毕竟能直接立马写入
降低GC影响,毕竟不在java进程里面控制
- 提高系统吞吐量,毕竟能直接立马写入
- 缺点
- 资源管理复杂性,不受java管控,监控,排查问题等不好做,可能算是隐藏逻辑
- 刷盘机制:
-----------------------------------------------------------------------------------20240624-----------------------------------------------------------------------
很久没出去面试了,6月抽空面了一次,问到了关于Rocketmq的通信模型,这一块是缺失的,后续等我学习完netty再来继续升入
2611

被折叠的 条评论
为什么被折叠?



