具体需要从 生产者和消费者两个方面来讲:
生产者:
1. 分区机制:
Kafka的核心机制之一是分区(Partition)。每个主题(Topic)可以被分割成多个分区,而消息在发布时会被追加到特定的分区中。在每个分区内部,消息是按照它们被追加的顺序来存储的,因此保证了分区内的消息顺序性。
2. 分区器:
生产者(Producer)在发送消息时可以指定一个分区器(Partitioner)来决定消息应该发送到哪个分区。分区器通常基于消息的某个属性(如key的哈希值)来决定分区。这样,具有相同key值的消息会始终被发送到同一个分区,从而确保了这些消息的顺序性。
3. 消息key:
生产者可以通过为消息设置特定的key来确保消息的顺序。例如,如果业务逻辑要求相同用户的消息保持顺序,那么生产者可以使用用户ID作为消息的key。这样,所有来自同一用户的消息都会被发送到同一个分区,并按顺序存储和消费。
备注:有可能发送的时候生产者 1 2 3三个消息其中 第二个消息因为网络或者其他原因党搁了一会,导致 发到 kafka里面 变成了 132 ,为了避免这个情况我们可以开启kafak的生产端消息幂等性(需要在生产端配置参数enable.idempotence = true,当幂等性开启的时候acks必须即为all。)
什么是幂等性,为什么要实现幂等性?分布式系统中,一些不可控因素有很多,比如网络、OOM、FullGC等。在Kafka Broker确认Ack前,有可能出现网络异常、FullGC、OOM等问题时导致Ack超时,Producer会进行重复发送。注,在未达到最大重试次数前,会自动重试(非应用程序代码写的重试) 总结:生产者可以通过将消息指定分区,指定特定的key 加上开启消息幂等性 保证消息的有序性。
消费者:
4. 消费者组配置:
在消费者组(Consumer Group)中,每个分区通常只会被一个消费者实例消费。这意味着,如果生产者确保了消息在分区内的顺序性,那么消费者也将按照相同的顺序消费这些消息。这要求消费者组配置得当,确保每个分区只被一个消费者消费。
总结:消费者可以一个 topic,一个 partition,一个 consumer,内部单线程消费。保证消息的有序性。
OK 。生产消息端基于这种情况基本可以保证顺序性。但是问题如下:
问题
比如说我们建了一个 topic,有三个 partition。生产者在写的时候,其实可以指定一个 key,比如说我们指定了某个订单 id 作为 key,那么这个订单相关的数据,一定会被分发到同一个 partition 中去,而且这个 partition 中的数据一定是有顺序的。
消费者从 partition 中取出来数据的时候,也一定是有顺序的。到这里,顺序还是 ok 的,没有错乱。接着,我们在消费者里可能会搞多个线程来并发处理消息。因为如果消费者是单线程消费处理,而处理比较耗时的话,比如处理一条消息耗时几十 ms,那么 1 秒钟只能处理几十条消息,这吞吐量太低了。而多个线程并发跑的话,顺序可能就乱掉了。
解决方案如下:
消费者使用内存队列,将拿到的具有相同 key 的数据都存到同一个内存 queue;然后对于 N 个线程,每个线程分别消费一个内存 queue 即可,这样就能保证顺序性。
标签:顺序,消费者,生产者,分区,kafka,保证,消息,key,有序性 From: https://www.cnblogs.com/paimianbaobao/p/18217511