Kafka 如何保证消息顺序性

文章目录

分区策略

Kafka 的消息会被生产者发送到分区 Partition 中,然后消费者通过获取分区中的消息来完成消费操作。所以Kafka不仅有主题 Topic这个概念,也引入分区 Partition 这个概念来实现队列的可用性、伸缩性、吞吐量,不过也有一定的代价,就是需要解决消费无序、丢失 等比较关键的问题,当前主要的分区策略有以下4种。

轮询

当生产者向Kafka发送消息时,如果既没有指定key,又没有指定 Partition,就会使用默认的分区器,默认按照轮询策略向分区进行数据发送。轮询很好理解,字面意思就是每次消息发送给不同的分区,例如:

  • 第一次:发送给分区1
  • 第二次:发送给分区2
  • 第三次:发送给分区3
  • 第四次:发送给分区1
  • 不断循环...

轮询策略 尽可能保证每个分区中的消息数量均衡,如下图所示:

随机

当生产者向Kafka发送消息时,如果既没有指定key,又没有指定 Partition。虽然现在默认策略应该是轮询 ,但是以前老版本Kafka的分区策略其实采用的是随机 ,轮询更好理解,每次发送消息时都会发送给不同的分区,没有任何规律,如下图所示:

按 Partition 路由

上面提到的两种方式,都是不指定key和分区,该策略就是在消息发送之前,就指定好该消息要发送到具体哪个分区中,如下图所示:

按 key 路由

指定 key 路由方式是我们开发过程中Kafka主要使用的方式,在向分区发送消息之前,一般都会为该消息指定 key,这样 Kafka 会根据消息的 key 进行哈希运算,然后与分区的数量进行取模操作,这样就能判定当前消息回路由到哪个分区,所以每次相当 key 的消息一定会在同一个分区当中(前提分区没有发生扩缩容), 如下图所示:

顺序性保证

有一个前提需要了解:Kafka保证单个分区内顺序,不保证多个分区间的全局顺序

想要保证消息顺序性,势必要牺牲Kafka吞吐量,保证消费顺序性最简单的方式莫过于为单个主题单个分区 ,这样就能保证每条消息一定是顺序的,对应的消费者 也要使用单线程或者保证消费顺序的线程模型。但是这样反而违背了分区这个概念的初衷,正常生产环境也几乎没有这样做的,这个方式绝大部分场景并不可取。❌

所以想要保证顺序性,通常最佳实践如下:

  • 首先,指定消息key会进行哈希 + 取模方式定位具体分区,然后进行消息发送,这样同一分区消息本身就是按顺序排列。
  • 其次,在消费者端同样也要控制,不能多线程对消息进行处理,这样会因为并发问题打乱消费顺序,要确保消费者单线程处理一个分区的消息
  • 最后,设置下述 Kafka 相关参数,这样就避免发送重试消息乱序问题:
shell 复制代码
# 确认应答机制:all表示所有分区副本消息同步完毕
acks=all
# 消息发送失败重试次数,如果发送失败,会重新进行消息发送
retries > 0
# 允许生产者在同一个连接上同时发送、等待确认的最大请求数
max.in.flight.requests.per.connection = 1
相关推荐
oMcLin11 小时前
如何在Oracle Linux 8.4上搭建并优化Kafka集群,确保高吞吐量的实时数据流处理与消息传递?
linux·oracle·kafka
码农水水11 小时前
中国邮政Java面试:热点Key的探测和本地缓存方案
java·开发语言·windows·缓存·面试·职场和发展·kafka
前端不太难15 小时前
从本地到多端:HarmonyOS 分布式数据管理实战详解
分布式·状态模式·harmonyos
Yeats_Liao15 小时前
MindSpore开发之路(二十五):融入开源:如何为MindSpore社区贡献力量
人工智能·分布式·深度学习·机器学习·华为·开源
我爱娃哈哈17 小时前
SpringBoot + Seata + Nacos:分布式事务落地实战,订单-库存一致性全解析
spring boot·分布式·后端
掘金-我是哪吒18 小时前
Kafka配套的Zookeeper启动脚本
分布式·zookeeper·云原生·kafka
超级种码19 小时前
Kafka四部曲之一:Kafka的核心概念
分布式·kafka
Java 码农20 小时前
RabbitMQ集群部署方案及配置指南09
分布式·rabbitmq
u01040583620 小时前
基于 Kafka Exactly-Once 语义保障微信群发消息不重复不丢失
分布式·kafka·linq
超级种码20 小时前
Kafka四部曲之二:核心架构与设计深度解析
分布式·架构·kafka