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
相关推荐
Devin~Y3 小时前
高并发电商与AI智能客服场景下的Java面试实战:从Spring Boot到RAG与向量数据库落地
java·spring boot·redis·elasticsearch·spring cloud·kafka·rag
小白学大数据6 小时前
Scrapy 分布式爬虫:大规模采集汽车之家电车评论
开发语言·分布式·爬虫·scrapy
仗剑_走天涯7 小时前
hadoop reduce阶段 对象重用问题
大数据·hadoop·分布式
电磁脑机7 小时前
无总线场同步:意识本质、AGI困境与脑机革命的核心理论重构
分布式·神经网络·架构·信号处理·agi
半桶水专家8 小时前
kafka数据删除策略详解
分布式·kafka
一个有温度的技术博主8 小时前
Lua语法进阶:函数封装与条件控制的艺术
redis·分布式·缓存·lua
无心水8 小时前
2、5分钟上手|PyPDF2 快速提取PDF文本
java·linux·分布式·后端·python·架构·pdf
Jackyzhe8 小时前
从零学习Kafka:位移与高水位
分布式·学习·kafka
roman_日积跬步-终至千里8 小时前
【系统架构师-案例题-分布式数据缓存架构】22年下(3)分布式仓储货物管理系统
分布式·缓存·系统架构
鬼先生_sir8 小时前
SpringCloud-Stream + RocketMQ/Kafka
spring cloud·kafka·rocketmq·stream