RocketMQ使用/源码享用
RocketMQ
当前笔者使用版本为 RocketMQ 5.3.4-SNAPSHOT
保证顺序消费的四把锁
- 分布式锁(保证加入全局分区锁时的并发安全–broker中维护,类比redis
- 全局分区锁(key为消费者组名(因为多个topic被多个消费者组订阅),维护队列与单个消费者实例的锁)
- Synchronized(保证一个消费者实例只有一个线程拉取消息、消费消息、提交消息)
让单个实例的一个线程进行校验、拉取消息、消费消息、提交消息
- ReentrantLock(给队列加入一个锁,告诉别人我要进行使用,防止rebalance时队列调度到其他消费者组
可以看到processQueue的setDropped方法就是在重平衡的时候进行的
关于Kafka与RocketMQ的重平衡
对于顺序队列来说不会参与重平衡分配
RebalanceImpl&updateMessageQueueAssignment()
维度 | Kafka | RocketMQ |
---|---|---|
触发机制 | 实时事件触发(消费者加入/离开、心跳失败、订阅变化) | 定时轮询触发(默认 20 秒一次) |
协调机制 | 中央协调器(GroupCoordinator)统一调度、Leader 选举 | 客户端自我协商,每个消费者独立发起 |
是否暂停消费全组 | 整个组暂停消费直到分配完成 | 局部影响,其余消费者继续工作 |
分配者角色 | Leader 消费者计算新分配方案 | 每个客户端各自执行分配策略 |
分配粒度 | Partition 粒度 | MessageQueue 粒度 |
稳定性策略(新版) | 支持 Cooperative Sticky(渐进式分配) | 默认是平均分配策略,可自定义 |
消费者变动频率容忍性 | 容忍性差(高频上下线会频繁 Rebalance) | 容忍性强(轮询机制稳定) |
RocketMQ 重平衡—>RebalanceService
RebalanceImpl&doReblance
public boolean doRebalance(final boolean isOrder) { |
简单举例
有一个Topic 有6个queue/partition
消费者实例A,B
新加入实例C
Kafka行为
- 系统出发Rebalance,暂停所有消费者
- 由Leader消费者重新分配分区
- 所有消费者接收新分配后再恢复消费
1. 所有消费者发送 JoinGroup 请求给 GroupCoordinator(Broker); |
RocketMQ行为
- 每个客户端RebalanceService启动&定时轮询
- 发现C加入后,队列局部重新分配
- C接手部分队列,其余消费者照常消费
也就是说可能是A和C进入分配(此时A的定时器刚好触发然后发现C实例加入了)B正常消费不受影响
总结:RocketMQ 的 Rebalance 存在天然“延迟生效”机制,新加入的消费者不会立刻就能分配到队列
时序演示
时间轴: T0 T+5s T+20s T+21s |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 一只末影酱的小屋!