上一篇文章「保证严格的消息顺序消费究竟有多难?」简单描述了对消息顺序消费的一些理解,上一篇文章中的第二个故障问题,感觉没描述清楚,现在我以 Kafka 为例子,继续分析一波。
从上一篇文章中分析可知,想要保证消息顺序消费,只需要保证生产端消息发送处在同一分区即可,但现实情况往往会遇到很多意外情况,下面我就盘点一下 Kafka 集群中有哪些意外情况会打乱消息的顺序。
1、分区变更的情况
假设有集群中有两个分区的主题 A,生产端需要往分区 1 发送 3 条顺序消息,我们都知道生产端是根据消息 Key 取模计算决定消息发往哪个分区的,如果此时生产端发送第三条消息前,主题 A 增加了一个分区,生产端根据 Key 取模得出的分区号就不一样了,第三条消息路由到其它分区,结果就是这三条顺序消息就不在同一个分区了,此时就不能保证这三条消息的消费顺序了。
2、分区不变更
1.1、分区单副本
假设此时集群有两个分区的主题 A,副本因子为 1,生产端需要往分区 1 发送 3 条顺序消息,前两条消息已成功发送到分区 1,此时分区 1 所在的 broker 挂了(由于副本因子只有 1,因此会导致分区 1 不可用),当生产端发送第三条消息时发现分区 1 不可用,就会导致发送失败,然后尝试进行重试发送,如果此时分区 1 还未恢复可用,这时生产端会将消息路由到其它分区,导致了这三条消息不在同一个分区。
1.2、分区多副本
针对分区单副本情况,我们自然会想到将分区设置为多副本不就可以避免这种情况发生吗?多副本情况下,发送端同步发送,acks = all,即保证消息都同步到全部副本后,才返回发送成功,保证了所有副本都处在 ISR 列表中,如果此时其中一个 broker 宕机了,也不会导致分区不可用的情况,看起来确实避免了分区单副本分区不可用导致消息路由到其它分区的情况发生。
但我想说的是,还有一种极端的现象会发生,当某个 broker 宕机了,处在这个 broker 上的 leader 副本就不可用了,此时 controller 会进行该分区的 leader 选举,在选举过程中分区 leader不可用,生产端会短暂报 no leader 警告,这时生产端也会出现消息被路由到其它分区的可能。