zoukankan      html  css  js  c++  java
  • RocketMQ如何保证队列完全顺序消费

    在知乎看到了这个问题,总结下(发现某乎社会热点问题讨论没法看,专业知识问题老哥们答得可是很ok)

    首先,根据RocketMQ的存储机制,RocketMQ是支持顺序消费的。但这个顺序,不是全局顺序,只是分区(Message Queue)顺序。要全局顺序只能一个分区(Message Queue)。

    接下来,我们从生产者和消费者两方面的逻辑来考虑这个问题。

    Consumer

    消费消息的顺序要同发送消息的顺序一致。由于 Consumer 消费消息的时候是针对 Message Queue 顺序拉取并开始消费,且一条 Message Queue 只会给一个消费者(集群模式下)(一个Topic的多个队列分配给一个group,然后group的多个消费者各自分到队列进行消费,默认平均分配),所以能够保证同一个消费者实例对于 Queue 上消息的消费是顺序地开始消费(不一定顺序消费完成,因为消费可能并行)。

    Producer

    发送消息的时候,消息发送默认是会采用轮询的方式发送到不同的queue,需要的话生产者发送的时候可以用 MessageQueueSelector 为某一批消息(通常是有相同的唯一标示id)选择同一个 Queue ,则这一批消息的消费将是顺序消息(并由同一个consumer完成消息)。或者 Message Queue 的数量只有 1 ,但这样消费的实例只能有一个,多出来的实例都会空跑。

    但的确会有一些异常场景会导致乱序。如Broker 宕机或重启,导致写入队列的数量上出现变化。这样在MessageQueueSelector之中的逻辑无论是轮训还是取模就会出问题,由于队列总数发生发化,消费者也会触发负载均衡,而默认地负载均衡算法采取哈希取模平均,这样负载均衡分配到定位的队列会发化,使得队列可能分配到别的实例上,则会短暂地出现消息顺序不一致。除非选择牺牲failover特性(即 Broker 集群中只要有一台机器不可用,则整个集群都不可用),如master挂了无法发通接下来那批消息,但是服务可用性大大降低。

    讨论完顺序消费的逻辑,我们来看一看实际场景中的问题,扩容是我们可能会遇到的场景,我们来思考下在扩容情况下,如何在不停写的情况下保证顺序消费?

    顺序消息扩容的过程中,如何在不停写的情况下保证消息顺序?

    1成倍扩容,实现扩容前后,同样的 key,hash 到原队列,或者 hash 到新扩容的队列。

    2扩容前,记录旧队列中的最大位点。

    3对于每个 Consumer Group ,保证旧队列中的数据消费完,再消费新队列,也即:先对新队列进行禁读即可。

    参考资料

    rocketmq怎么保证队列完全顺序消费?

  • 相关阅读:
    code3728 联合权值
    Codevs 4600 [NOI2015]程序自动分析
    code1540 银河英雄传说
    code1074 食物链
    堆排序
    哈夫曼树与哈夫曼码
    优先队列用法
    code1154 能量项链
    code1225 八数码Bfs
    javascript5
  • 原文地址:https://www.cnblogs.com/wunsiang/p/12765152.html
Copyright © 2011-2022 走看看