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
相关推荐
此时不提桶,更待何时8 小时前
06-23-A-RabbitMQ生态集成详解
分布式·rabbitmq
m0_6464299713 小时前
RabbitMQ 核心知识总结(生产实战版)
分布式·rabbitmq
DBA_G15 小时前
GBase 8c分布式数据库客户端工具 gsql
数据库·分布式
chunyublog15 小时前
Spark 词频统计练习
大数据·分布式·spark
ClouGence16 小时前
开源数据库管理工具 CloudDM 4.4.0 发布,新增 Kafka、SAP HANA 数据源
数据库·kafka
acrel717 小时前
高速公路分布式光伏并网电能质量与安全保护方案应用
分布式·安全
RobinXYuan17 小时前
【Kafka 源码手记】01 从消息队列到 Event Streaming
kafka·源码阅读
IT小小猪18 小时前
# Hadoop 3.3.6 完全分布式集群部署知识库
hadoop·分布式·eclipse
此时不提桶,更待何时18 小时前
06-24-B-RabbitMQ面试与生产事故实战
分布式·面试·rabbitmq
来福猿19 小时前
分布式锁 Redis 实现源码分析:SETNX、过期时间与可重入设计
数据库·redis·分布式