RocketMQ

https://zhuanlan.zhihu.com/p/83505477

 

 

保证消息局部顺序消费的重点在于:

  1. 生产者组通过计算,将相同 ID 的订单消息发往同一个 MessageQueue
  2. 消费者组通过分别位于 Broker 和客户端的两把锁,保证对该 MessageQueue 内消息的顺序消费

发往同一个 MessageQueue 保证了该 MessageQueue 内消息是局部有序的,但是无法保证全局有序,想要全局有序?那这个 Topic 只能配一个 MessageQueue,然后全部消息都发到这一个 MessageQueue 中。一般来说,局部有序已经可以满足绝大部分应用场景了。

生产端的保证达到了,下面就是消费端,依靠的是两把锁,分别位于 Broker 侧和消费者实例客户端侧。Broker 侧的锁是 MessageQueue 粒度的,保证同一时间至多只有一个消费者实例消费该 MessageQueue

你可能疑惑,本来不就是一对一的关系么?原因是在消费者组进行 Rebalance 的时候可能会造成某个时间窗口内单个 MessageQueue 被多个消费者实例同时消费,这里通过加锁限制了这种情况。一旦启动时加锁失败,意味着该 MessageQueue 还在被其他消费者实例锁定,因此不创建相应的消息拉取任务,等到锁被释放或者超时(默认 60s)。加锁成功后消费者实例还会每隔 20s 定时锁定该 MessageQueue 一次。

消费者实例侧由于可能同时负责消费多个 MessageQueue,因此采用了线程池消费消息,需要在客户端提供加锁的方式保证单个 MessageQueue 内的消息同一时间仅被一个线程消费。

 

 

Rebalance

消息队列系统中,经常会出现 Broker 实例的增删、Topic 的增减、Topic 下 MessageQueue 数目的增减、消费组实例数目的增减等情况,它们都会触发消费关系的重新分配,这个过程称之为 Rebalance

RocketMQ 的 Rebalance 机制有主动和被动之分,主动意为消费者实例每隔 20s 会定时计算自己的消费拓扑并和内存中的对比,一旦发现部分 MessageQueue 不再是自己负责消费,则停止对它的消息拉取任务;如果有新的 MessageQueue 变为自己负责,则创建对它的消息拉取任务。

被动意为,Broker 可以主动通知某个消费组下的所有实例,要求它们立即开始一次 Rebalance,常用于新的消费者实例加入、或者 Broker 检测到有消费者实例心跳失联等情况,下面是一个消费者实例新加入的场景。

RocketMQ 的 Rebalance 由于部分时刻的视图可能存在不一致,因此单次 Rebalance 并不能完全保证一定达到最终效果,但是由于它是一种周期性的任务,所以最终系统里的 MessageQueue 会被分配完全。

RocketMQ 的 Rebalance 机制依靠客户端各自单独计算得到,Kafka 新版本中则依靠 Consumer Leader 单点计算后再上传至 Group Coordinator,由它下发至每个消费者实例进行更新。

这两种方式各有优缺点,通常来说,单点计算可以最大程度减小视图不一致导致的频繁 Rebalance 现象(但也不能杜绝),但是缺点在于逻辑复杂,消费者组和 Broker 中都需要选取单点,一个负责计算一个负责下发通知;客户端计算实现上更简单,彼此独立,通过周期性任务最终也能完成重新分配的任务,但是由于客户端彼此获取的视图不做校验,因此可能存在由于视图不一致导致的重复消费和频繁 Rebalance

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值