在业务中使用kafka发送消息异步消费的场景,而且须要实如今消费时实现顺序消费, 利用kafka在partition内消息有序的特色,实现消息消费时的有序性。网络
一、在发送消息时,经过指定partition hash
二、consumer 消费消息时,须要使用亲缘性线程池进行消费,才能实现消息的基本有序。不然即便经过发送时指定partition,在消费端因为线程池的异步消费,消息之间的处理都是并发进行的,消息就会被打乱。
上面的方式基本能够实现消息的消费顺序性,除了在极端场景下,好比:并发
一、进程A 在T0时刻发送一个消息A
二、进程B在T1时刻发送了一个消息B。
因为T1>T0,而且进程A和进程B发送消息都是同一个hash partition,消息理论上在partition内消息A是在消息B前被消费的。但假如进程A和进程B出于不一样的机房等缘由,致使在发送消息时进程A的消息因为网络缘由,要比进程B更晚发送成功,那么就会致使消息B是在消息A以前。异步
多集群模式下分布式
因为kafka的有序性,只是在单集群的单partition内是有效的,因此当多集群模式下,各个集群之间的消息就不知足了有序的条件。虽然因为每一个集群都是使用相同的配置,都映射同一个consumer进程消费,以下:spa
可是因为cluster-1-partition-5和cluster-2-partition-5两个partition之间的是不一样的partition,因此没有办法作到绝对有序。线程
同时因为conusmer-1会出现跨机房消费的多个集群的状况,因此本来在单集群模式下,因为网络耗时而致使的消息前后顺序,在多集群状况下就会增大。目前跨集群消费延迟在2-10ms之间,因此在实际业务处理中遇到了消息A比消息B早发送,在消息B先到达的场景。
blog
因为须要在consume端实现顺序消费,须要使用亲缘性线程池以确保同一个sku在同一个线程中消费消息。这种方式当某个sku的消息量特别大时,那么就会阻塞了io线程,致使其余消息也出现大量延迟。目前默认io线程拉取消息按broker来的,应该是等同于broker数量。虽然能够增长io线程数来减缓这个状况,但依然会存在这个场景。
进程
在分布式场景下要实现消息消费强顺序性须要付出很大的成本,而且须要作到绝对顺序十分困难。若是能够容忍这个消费的无序性,那么每每就不须要用到顺序消费了。 以上分析为实际应用中遇到的坑,仅供参考,欢迎拍砖。
ps:
业务进程在发送kafka消息后,会有一个linger时间,等待linger时间以后再发送.rem