kafka集群分布式下,如何保证消息的有序性?

前言

kafka可以保证同一个partition的消息的有序性,不能保证不同partition消息的有序性。

为什么kafka不设计成不同partition消息的有序性?

如果要保证多个partition有序,那么既要保证broker保存消息的顺序,又要保证消费消息时的顺序。如果partition1堵了,为了保证消费的有序性,其它partition都只能等待了,这样kafka的多partition还有什么意义呢。

kafka producer 发送消息时,是如何确保单一partition的有序性的?

加锁

kafka producer 发送消息时,是如何确保单一partition的有序性
kafka producer 发送消息时,是如何确保单一partition的有序性

结合我们自己的业务场景,可以在发送消息时,想保证顺序的同一批数据指定相同的message key,因为kafka可以保证相同的key进入同一partition。

比如,用kafka发送GPS数据时,有三个参数(partition key message),其中partition和key是可选的,我们可以通过指定partition或者指定key为gps设备的imei号,这两者都可以保证同一台gps设备的数据进入同一个partition。

并且kafka也保证了消费端同一个partition的消息只被一个Consumer消费。

牺牲性能的做法

当然,我们也可以在创建topic时,只指定一个partition,这样也能保证消息的有序性,不过这样就浪费了kafka的分布式高吞吐的特性,所以不推荐这样做。

消息发送失败,重试机制启动的情况下,如何保证消息的有序性?

正常的理想状态下,上面的配置的确没问题,可是有时,我们还需要考虑消息发送失败的情况。

一般我们会设置重试机制来解决消息发送的问题,如果是非临时性错误导致的消息发送失败(如消息体过大),那么再怎么重试也是没有意义的。如果是临时性错误导致消息发送失败(如网络抖动或分区找不到首领),那么可以设置producer的retries,该值默认是0,比如设置3,重试3次。但是这样可能就会造成乱序的问题,比如消息A先发送,但是发送失败了,等消息B发完后,消息A又重试成功了,这就造成了message A 和 B 的乱序。

如何解决呢?

可以借助 max.in.flight.requests.per.connection 配置项来解决,该参数指定了生产者在收到服务器响应前可以发送几个消息。该值默认是5。它的值越高,吞吐量就越高,但是也越占内存。我们可以把它设为1,这样就保证了即使发生重试,消息也会严格的有序。

但是,还是老问题,高可靠性和高性能,择其一必然会舍其一,这样的配置可以保证消息的可靠性,但是性能也会下降。

0.11版本后,kafka引入事务机制可保证producer挂掉重启后依然保证有序。

 

 

0

发表评论

您的电子邮箱地址不会被公开。