layout: post title: "保证严格的消息顺序消费究竟有多难?" categories: Kafka tags: message sequential 顺序消息
我觉得这个问题问得很频繁,而且非常经典,在这里我就以 Kafka 为例子,说说我对 Kafka 顺序消息的一些理解吧,如有理解不对的地方麻烦留言指点一下。
通常我们在说顺序消费指的是生产者按照顺序发送,消费者按照顺序进行消费,听起来简单,但做起来却非常困难。
我们都知道无论是 Kafka 还是 RocketMQ,每个主题下面都有若干分区(RocketMQ 叫队列),如果消息被分配到不同的分区中,那么 Kafka 是不能保证消息的消费顺序的,因为每个分区都分配到一个消费者,此时无法保证消费者的消费先后,因此如果需要进行消息具有消费顺序性,可以在生产端指定这一类消息的 key,这类消息都用相同的 key 进行消息发送,kafka 就会根据 key 哈希取模选取其中一个分区进行存储,由于一个分区只能由一个消费者进行监听消费,因此这时候消息就具有消息消费的顺序性了。
但以上情况只是在正常情况下可以保证顺序消息,但发生故障后,就没办法保证消息的顺序了,我总结以下两点:
1、当生产端是异步发送时,此时有消息发送失败,比如你异步发送了 1,2,3 消息,2 消息发送异常重试发送,这时候顺序就乱了;
2、当 Broker 宕机重启,由于分区会发生重平衡动作,此时生产端根据 key 哈希取模得到的分区发生变化,这时会发生短暂消息顺序不一致的现象。
针对以上两点,生产端必须保证单线程同步发送,这还好解决,针对第二点,想要做到严格的消息顺序,就要保证当集群出现故障后集群立马不可用,或者主题做成单分区,但这么做大大牺牲了集群的高可用,单分区也会另集群性能大大降低。