kafka简介

简介

Apache kafka 是一个分布式的基于push-subscribe的消息系统,它具备快速、可扩展、可持久化的特点。它现在是Apache旗下的一个开源系统,作为hadoop生态系统的一部分,被各种商业公司广泛应用。它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、storm/spark流式处理引擎。

kafka简介

特性

  • 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒

  • 可扩展性:kafka集群支持热扩展

  • 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失

  • 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)

  • 高并发:支持数千个客户端同时读写


架构组件

Kafka中发布订阅的对象是topic。我们可以为每类数据创建一个topic,把向topic发布消息的客户端称作producer,从topic订阅消息的客户端称作consumer。Producers和consumers可以同时从多个topic读写数据。一个kafka集群由一个或多个broker服务器组成,它负责持久化和备份具体的kafka消息。

  • Topic:消息存放的主题

  • Producer:生产者,负责push消息到指定的Broker的Topic中

  • Consumer:消费者

  • Broker:Kafka的服务实例,主要负责创建Topic,存储Producer所发布的消息,记录消息处理过程,先将消息保存到内存中,再落地到磁盘

  • Replication-factor:复制因子(kafka容错机制),即副本数量,一般与Broker数量保持一致

  • Partitions:分区(每个分区只能被同一个消费者组内的一个消费者消费)

  • Leaders:选举partition中的副本为leader,负责处理读写

  • Follower: 未被选举为leader的副本为follower,负责备份数据

  • Zookeeper:注册消息,用于保存broker节点信息,维护ISR和OSR队列,partition的offset等(ZK在kafka2.8版本之后移除,offset保存在本地)


副本同步机制

kafka 0.8以后,提供了HA机制,就是replica副本机制。每个partition的数据都会同步到其他机器上,形成自己的多个replica副本。然后所有replica会选举一个leader出来,那么生产和消费都跟这个leader打交道,然后其他replica就是follower。写的时候,leader会负责把数据同步到所有follower上去,读的时候就直接读leader上数据即可。

[图片上传失败...(image-6f7b38-1743417387765)]

Kafka 生产者ack机制

  • ack=0:

    • 意义:生产者在成功将消息发送给服务端之后不等待任何确认

    • 结果:生产者不知道消息是否成功到达服务端,容易造成消息丢失

  • ack=1:

    • 意义:生产者在成功将消息发送给服务端之后,等待leader的确认

    • 结果:意味着leader节点成功接收数据,但是不一定同步了其他副本

  • ack=all 或 ack=-1:

    • 意义:生产者在成功将消息发送给服务端之后,等待所有partition的副本确认

    • 结果:当所有副本都接收到数据之后,才认为消息被成功提交

Kafka 如果设置了ack(ack!=0),需要设置超时时间(retry.backoff.ms)和重试次数(retries)


ack过程中出现网络问题,导致生产者重复发送消息怎么处理?

重复产生的核心原因
  • 超时与重试机制 当 Producer 发送消息后,若在 request.timeout.ms(默认 30 秒)内未收到 Broker 的 ack 确认,Producer 会认为消息发送失败并触发重试(retries 参数控制重试次数)。 风险场景

    • Broker 实际已成功写入消息,但 ack 响应因网络延迟未及时到达 Producer。

    • Producer 重试时,Broker 会再次写入相同的消息(若未启用幂等性),导致消息重复。

  • Broker 的写入机制 Kafka 的 Partition 日志是仅追加(append-only)的,即使消息内容相同,重试时也会被当作新消息写入(除非开启幂等性)。

避免重复的解决方案

(1) 启用 Producer 幂等性

  • 配置方式: 在 Producer 中设置 enable.idempotence=true(需同时满足 acks=allretries > 0)。

  • 原理

    • Producer 为每个消息分配唯一 PID(Producer ID)序列号

    • Broker 根据 PID + 分区号 + 序列号 去重,拒绝重复消息。

  • 适用场景: 单 Producer 实例内保证 Exactly-Once 语义,避免因重试导致的重复。

(2) 使用 Kafka 事务

  • 配置方式

    • 设置 transactional.id 并调用 initTransactions()beginTransaction()commitTransaction()
  • 原理

    • 事务机制结合幂等性,确保跨多个 Partition 和 Consumer 的原子性操作。

    • Broker 会记录事务状态,中断的事务自动回滚。

  • 适用场景: 需要跨多个消息或“读-处理-写”链路的 Exactly-Once 语义(如 Kafka Streams)。

(3) 业务端去重

  • 实现方式

    • 在消息中携带唯一标识(如 UUID 或业务主键)。

    • 消费者端根据唯一标识去重(如写入数据库时检查主键冲突)。

  • 适用场景: 无法启用幂等性或事务的旧版本 Kafka,或需要兼容其他消息系统的场景。


ISR 机制

Kafka 服务端根据副本同步的情况,分成了三个集合:

AR(Assigned Replicas):包括ISR和OSR

ISR(In-sync Replicas):和leader保持同步的副本集合,可以认为是可靠数据(leader故障之后会在这个集合重新选举)

OSR(Out-sync Replicas):和leader副本同步失效的副本集合(副本还会继续同步数据,同步成功之后会进入ISR)


Kafka 数据持久化机制

Kafka 默认使用操作系统的页缓存(page cache)机制,将消息写入内存中的页缓存,而非立即刷盘(高吞吐的原因)

默认情况下,Kafka 通过以下两个参数控制主动刷盘:

  • log.flush.interval.messages:累计多少条消息后触发刷盘(默认 Long.MAX_VALUE,即不主动触发)

  • log.flush.interval.ms:间隔多少毫秒后触发刷盘(默认 null,即不主动触发) 实际默认行为:依赖操作系统后台线程(如 Linux 的 pdflush)自动刷盘,通常延迟约 30 秒

Broker 端配置

  • 强制刷盘 修改 log.flush.interval.messageslog.flush.interval.ms,例如:

    • log.flush.interval.messages=1 # 每条消息都刷盘(极端情况,性能极低)

    • log.flush.interval.ms=1000 # 每秒刷盘一次

此配置会显著降低吞吐量,仅适用于对数据丢失零容忍的场景。


Kafka 数据模型与消息存储机制

[图片上传失败...(image-4d351-1743417387765)]

在同一个Topic下,一个partition对应一个唯一的文件夹,在文件夹下,kafka 消息是采用 Segment File的存储方式进行存储

Segment File:Segment由.index文件和.log文件组成,将大文件拆分成小文件来存储(加快IO加载

.index文件:索引文件,以key-value格式存储,key-表示索引文件的第几条消息;value-表示这条消息在log file中的物理偏移量

.log文件:数据存储文件

如何通过 offset 找到 某一条消息呢?

  1. 首先会根据 offset 值去查找 Segment 中的 index 文件,因为 index 文件是以上个文件的最大 offset 偏移命名的所以可以通过二分法快速定位到索引文件。

  2. 找到索引文件后,索引文件中保存的是 offset 和对应的消息行在 log 日志中的存储行号,因为 Kafka 采用稀疏矩阵的方式来存储索引信息,并不是每一条索引都存储,所以这里只是查到文件中符合当前 offset 范围的索引。

  3. 拿到 当前查到的范围索引对应的行号之后再去对应的 log 文件中从 当前 Position 位置开始查找 offset 对应的消息,直到找到该 offset 为止。

每一条消息的组成内容有如下字段:

Copy
offset: 4964(逻辑偏移量) 
position: 75088(物理偏移量) 
CreateTime: 1545203239308(创建时间) 
isvalid: true(是否有效)
keysize: -1(键大小) 
valuesize: 9(值大小) 
magic: 2 
compresscodec: NONE(压缩编码) 
producerId: -1
producerEpoch: -1(epoch号) 
sequence: -1(序号) 
isTransactional: false(是否事务) 
headerKeys: []
payload: message_0(消息的具体内容)

Kafka pull & push

pull是指consumer来拉取消息(默认);push是指kafka主动推送消息给consumer

pull模式:根据consumer的消费能力进行数据拉取,可以批量拉或者单条拉;可以设置不同的提交方式实现不同的传输语义

缺点:如果kafka没有数据会导致consumer空循环(可以通过设置拉取数据为空或没达到一定数量阻塞来解决)

push模式:不会导致consumer循环等待

缺点:速率固定、忽略consumer的消费能力,可能导致拒绝服务或网络拥堵等情况


kafka常见问题

1、消息幂等性(重复消费)

重复消费只针对消费者端而言,消费者要保证消息的幂等性,一般要结合业务场景进行,主要有两种解决方案:

1)redis:消费数据后把消息的唯一键存到redis中,每次消费的时候去redis查一下key是否存在

2)mysql:消费数据后把消息的唯一键存到mysql中,每次消费的时候查mysql

2、数据丢失

  • 消费者:消费者自动提交offset的时候会有数据丢失的情况,改为手动提交offset可解决,极端情况下数据处理完后提交offset的时候挂了,可通过加幂等性操作解决

  • kafka:kafka某个broker宕机,重新选举leader时有数据未同步时会有消息丢失的情况,可通过设置参数(保证数据写入到每个副本后才算写入成功)解决

  • 生产者:设置acks=all即可避免丢失数据

3、顺序性

  • 生产者:生产者没有顺序性问题

  • kafka:partition内部有序,多个partition时无法保证顺序,对需要顺序消费的数据指定到同一个partition即可保证顺序

  • 消费者:同一个partition时,当消费者内部启用多线程时会导致顺序错乱,可在消费者内部启用内存队列来保证多线程的顺序

4、kafka 高性能高吞吐原因

  • 磁盘顺序读写:

    • Kafka 将消息按顺序追加(Append)到 Partition 日志文件末尾,避免机械硬盘磁头频繁寻道

    • 消费者按偏移量(Offset)顺序读取消息,充分利用操作系统的磁盘预读

    • 页缓存(page cache):消息直接写入内存页缓存,由操作系统异步刷盘,读操作优先访问缓存,减少物理磁盘 I/O

  • 零拷贝

    • 传统数据拷贝流程: 磁盘文件 → 内核缓冲区 → 用户空间缓冲区 → Socket 缓冲区 → 网卡 4 次上下文切换 + 2 次 CPU 拷贝

    • Kafka 优化(sendfile系统调用): 磁盘文件 → 内核缓冲区 → 网卡 2 次上下文切换 + 0 次 CPU 拷贝,减少 50% 以上 CPU 消耗

  • 分区分段+索引:分区是指partition,分段是指segment文件,索引是指segment里的.index索引

    • 分区(Partition)机制

      • 数据分片:每个 Topic 划分为多个 Partition,分布在不同 Broker 上。

      • 并行读写:生产者和消费者可同时向多个 Partition 写入/读取数据,充分利用集群资源。

      • 扩展性:通过增加 Partition 和 Broker,线性提升吞吐量。

    • 生产者负载均衡

      • 分区策略

        • 默认轮询(Round Robin)或按 Key 哈希,确保数据均匀分布。

        • 自定义策略支持业务特化路由。

    • 消费者组(Consumer Group)

      • 并行消费:同一消费者组内多个消费者实例分别消费不同 Partition,提升消费速度。

      • 水平扩容:增加消费者数量即可扩展消费能力(需 Partition 数量 ≥ 消费者数量)。

  • 批量处理(Batching)

    • 生产者端

      • 消息积累到 batch.size(默认 16KB)或 linger.ms(默认 0ms)后批量发送,减少网络请求次数。

      • 压缩(Compression):支持 GZIP、Snappy、LZ4、Zstandard,降低网络传输量(尤其文本类消息)。

    • Broker 端

      • 批量写入磁盘,减少磁盘寻址次数。
    • 消费者端

      • 批量拉取消息(max.poll.records 控制单次拉取数量)。
  • 直接操作页缓存(page cache):消息直接写入内存页缓存,由操作系统异步刷盘,读操作优先访问缓存,减少物理磁盘 I/O

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,321评论 6 543
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,559评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,442评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,835评论 1 317
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,581评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,922评论 1 328
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,931评论 3 447
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,096评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,639评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,374评论 3 358
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,591评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,104评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,789评论 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,196评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,524评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,322评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,554评论 2 379

推荐阅读更多精彩内容

  • 一、简介 Kafka 是一个分布式的基于发布/订阅模式的消息队列(Message Queue),主要应用于 大数...
    brayden_yang阅读 287评论 0 1
  • 1,消息引擎系统 1)Kafka是消息引擎系统。两个重要因素: 消息设计、传输协议设计。2)Kafka消息是结构化...
    沐兮_d64c阅读 1,907评论 0 13
  • Kafka的主要特点:1. 为发布和订阅提供高吞吐量,每秒可产生25万消息(50MB),每秒可处理55万消息(11...
    zi萱阅读 663评论 0 2
  • 1.kafka 集群的架构 Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partitio...
    本能帅阅读 268评论 0 1
  • 夜莺2517阅读 127,749评论 1 9