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
相关推荐
李九三7 分钟前
分布式限流
分布式
nlog3n2 小时前
分布式排行榜系统设计方案
java·分布式
拾忆,想起3 小时前
RabbitMQ事务机制深度剖析:消息零丢失的终极武器
java·开发语言·分布式·后端·rabbitmq·ruby
RunningShare3 小时前
云原生时代的数据流高速公路:深入解剖Apache Pulsar的架构设计哲学
大数据·中间件·apache·pulsar
z晨晨5 小时前
互联网大厂Java求职面试实战:Spring Boot与微服务场景深度解析
java·spring boot·redis·微服务·kafka·spring security·电商
野犬寒鸦6 小时前
从零起步学习Redis || 第五章:利用Redis构造分布式全局唯一ID
java·服务器·数据库·redis·分布式·后端·缓存
孟意昶8 小时前
Spark专题-第三部分:性能监控与实战优化(2)-分区优化
大数据·分布式·sql·性能优化·spark·big data
Hello.Reader9 小时前
Kafka 安全SASL 认证全栈实战从 JAAS 到 Kerberos、PLAIN、SCRAM、OAUTH 与委托令牌
分布式·安全·kafka
失散139 小时前
分布式专题——25 深入理解网络通信和TCP、IP协议
java·分布式·网络协议·tcp/ip·架构
山河亦问安20 小时前
基于Kafka+ElasticSearch+MongoDB+Redis+XXL-Job日志分析系统(学习)
mongodb·elasticsearch·kafka