跳至主要內容

元数据

格温·沙皮拉 托德·帕利诺 拉吉尼·西瓦拉姆 克里特·佩蒂约 8154 字大约 27 分钟...

元数据

[!abstract] Kafka权威指南(第2版)

  •  Kafka权威指南(第2版)|200
    Kafka权威指南(第2版)|200
  • 书名: Kafka权威指南(第2版)
  • 作者: 格温·沙皮拉 托德·帕利诺 拉吉尼·西瓦拉姆 克里特·佩蒂
  • 简介: 本书介绍Kafka的技术原理和应用技巧。内容包括如何安装和配置Kafka、如何使用Kafka API、Kafka的设计原则和可靠性保证,以及Kafka的一些架构细节,如复制协议、控制器和存储层。本书列举了一些非常流行的Kafka应用场景,比如基于事件驱动的微服务系统的消息总线、流式处理应用程序和大规模数据管道。通过学习本书,你不仅能够深入理解这项大数据核心技术,还能够将所学知识付诸实践,在生产环境中更好地运行Kafka,并基于它构建稳健的高性能应用程序。
  • 出版时间: 2022-11-01 00:00:00
  • ISBN: 9787115601421
  • 分类: 计算机-编程设计
  • 出版社: 人民邮电出版社
  • PC地址:https://weread.qq.com/web/reader/106329e0813ab77cfg010f2eopen in new window

高亮划线

第1章 初识Kafka

📌 我们把数据从源头移动到可以对它们进行分析处理的地方,然后再把得到的结果应用到实际场景中,这样才能确切地知道这些数据要告诉我们什么。 ^3300044310-9-518-583

  • 💭 数据快速转化为业务价值
    • ⏱ 2025-11-10 11:32:32

📌 当需要以一种可控的方式将消息写入不同的分区时,需要用到键
⏱ 2025-11-10 14:32:47 ^3300044310-9-3901-3929

📌 为了提高效率,消息会被分成批次写入Kafka。批次包含了一组属于同一个主题和分区的消息。如果每一条消息都单独穿行于网络中,那么就会导致大量的网络开销,把消息分成批次传输可以减少网络开销。
⏱ 2025-11-10 14:33:26 ^3300044310-9-4047-4147

📌 消息批次会被压缩,这样可以提升数据的传输和存储性能,但需要做更多的计算处理。
⏱ 2025-11-10 14:33:35 ^3300044310-9-4205-4243

📌 Kafka的消息通过主题进行分类。主题就好比数据库的表或文件系统的文件夹。主题可以被分为若干个分区,一个分区就是一个提交日志。消息会以追加的方式被写入分区,然后按照先入先出的顺序读取。需要注意的是,由于一个主题一般包含几个分区,因此无法在整个主题范围内保证消息的顺序,但可以保证消息在单个分区内是有序的。
⏱ 2025-11-12 10:07:30 ^3300044310-9-4980-5146

📌 一条消息会被发布到一个特定的主题上。
⏱ 2025-11-12 22:58:42 ^3300044310-9-6127-6145

📌 生产者会把消息均衡地分布到主题的所有分区中
⏱ 2025-11-12 22:59:02 ^3300044310-9-6152-6173

📌 某些情况下,生产者会把消息直接写入指定的分区,这通常是通过消息键和分区器来实现的
⏱ 2025-11-12 22:59:39 ^3300044310-9-6178-6218

📌 分区器会为键生成一个哈希值,并将其映射到指定的分区,这样可以保证包含同一个键的消息被写入同一个分区
⏱ 2025-11-12 22:59:47 ^3300044310-9-6219-6268

📌 消费者通过检查消息的偏移量来区分已经读取过的消息。偏移量(不断递增的整数值)是另一种元数据,在创建消息时,Kafka会把它添加到消息里。
⏱ 2025-11-12 22:58:29 ^3300044310-9-6435-6510

📌 消费者可以是消费者群组的一部分,属于同一群组的一个或多个消费者共同读取一个主题。
⏱ 2025-11-12 22:59:54 ^3300044310-9-6646-6693

📌 群组可以保证每个分区只被这个群组里的一个消费者读取。
⏱ 2025-11-12 23:00:02 ^3300044310-9-6693-6719

📌 如果一个消费者失效,那么群组里的其他消费者可以接管失效消费者的工作。
⏱ 2025-11-12 16:49:20 ^3300044310-9-7133-7167

📌 一台单独的Kafka服务器被称为broker
⏱ 2025-11-12 16:49:51 ^3300044310-9-7281-7303

📌 broker组成了集群。每个集群都有一个同时充当了集群控制器角色的broker(自动从活动的集群成员中选举出来)。控制器负责管理工作,包括为broker分配分区和监控broker。在集群中,一个分区从属于一个broker,这个broker被称为分区的首领。一个被分配给其他broker的分区副本(参见图1-7)叫作这个分区的“跟随者”。分区复制提供了分区的消息冗余,如果一个broker发生故障,则其中的一个跟随者可以接管它的领导权。
⏱ 2025-11-12 16:54:23 ^3300044310-9-7454-7692

📌 所有想要发布消息的生产者必须连接到首领,但消费者可以从首领或者跟随者那里读取消息。
⏱ 2025-11-12 16:53:35 ^3300044310-9-7692-7733

📌 它的设计目标是提供一个高性能的消息系统,该系统可以处理多种数据类型,并实时提供纯净、结构化的用户活动数据和系统指标。
⏱ 2025-11-17 11:32:32 ^3300044310-9-13729-13787

📌 数据为我们所做的每一件事提供了动力。——Jeff Weiner,LinkedIn前CEO
⏱ 2025-11-17 11:32:47 ^3300044310-9-13842-13919

📌 这个监控系统有很多不足,它使用的是轮询拉取指标的方式,指标之间的时间间隔较长,应用程序所有者无法管理属于自己的指标
⏱ 2025-11-17 11:31:00 ^3300044310-9-14169-14226

📌 同样,这个系统也有很多不足。XML文件格式无法保持一致,解析这种文件非常耗费计算资源。如果要修改已经创建好的活动类型,则需要在前端应用程序和离线处理程序之间做大量的协调工作。即使是这样,当数据结构发生变化时,系统仍然会崩溃。另外,批处理以小时为单位,无法实现实时处理。
⏱ 2025-11-17 11:31:21 ^3300044310-9-14409-14543

📌 他们的主要目标如下。● 使用推送和拉取模型解耦生产者和消费者。● 为消息传递系统中的消息提供数据持久化,以便支持多个消费者。● 通过系统优化实现高吞吐量。● 系统可以随着数据流的增长进行横向伸缩。
⏱ 2025-11-17 11:30:24 ^3300044310-9-15294-15508

第2章 安装Kafka

📌 如果服务器每天收到1 TB消息,需要保留7天,那么就需要7 TB的存储空间,另外还要为其他文件提供至少10%的额外空间。除此之外,还需要提供额外的缓冲区,用于应对消息流量的增长和波动。
⏱ 2025-11-19 11:10:11 ^3300044310-10-19611-19703

📌 Kafka本身不需要太多内存。一个每秒处理150 000条消息和每秒200 MB数据速率的broker,只需要5 GB堆内存,剩下的系统内存用于页面缓存。因为缓存了正在使用的日志片段,所以Kafka的性能得到了提升。这就是为什么不建议把Kafka同其他重要的应用程序部署在一起,因为它们需要共享页面缓存,从而会降低Kafka消费者的性能。
⏱ 2025-11-19 11:09:35 ^3300044310-10-20109-20278

第3章 Kafka生产者——向Kafka写入数据

📌 实例化好生产者对象后,接下来就可以开始发送消息了。发送消息主要有以下3种方式。
发送并忘记
把消息发送给服务器,但并不关心它是否成功送达。大多数情况下,消息可以成功送达,因为Kafka是高可用的,而且生产者有自动尝试重发的机制。但是,如果发生了不可重试的错误或超时,那么消息将会丢失,应用程序将不会收到任何信息或异常。
同步发送
一般来说,生产者是异步的——我们调用send()方法发送消息,它会返回一个Future对象。可以调用get()方法等待Future完成,这样就可以在发送下一条消息之前知道当前消息是否发送成功。
异步发送
调用send()方法,并指定一个回调函数,当服务器返回响应时,这个函数会被触发。
在接下来的几个例子中,我们将介绍如何使用上述3种方式来发送消息,以及如何处理可能出现的异常情况。
⏱ 2025-11-20 09:29:08 ^3300044310-11-4792-5365

📌 如果acks=0,则生产者不会等待任何来自broker的响应
⏱ 2025-11-20 09:44:07 ^3300044310-11-9841-9871

📌 如果acks=1,那么只要集群的首领副本收到消息,生产者就会收到消息成功写入的响应。
⏱ 2025-11-20 09:44:22 ^3300044310-11-10045-10087

📌 如果acks=all,那么只有当所有副本全部收到消息时,生产者才会收到消息成功写入的响应。
⏱ 2025-11-20 09:45:50 ^3300044310-11-10276-10321

📌 你会发现,为acks设置的值越小,生产者发送消息的速度就越快。也就是说,我们通过牺牲可靠性来换取较低的生产者延迟。不过,端到端延迟是指从消息生成到可供消费者读取的时间,这对3种配置来说都是一样的。这是因为为了保持一致性,在消息被写入所有同步副本之前,Kafka不允许消费者读取它们。因此,如果你关心的是端到端延迟,而不是生产者延迟,那么就不需要在可靠性和低延迟之间做权衡了:你可以选择最可靠的配置,但仍然可以获得相同的端到端延迟。
⏱ 2025-11-20 09:46:56 ^3300044310-11-10629-10844

📌 键有两种用途:一是作为消息的附加信息与消息保存在一起,二是用来确定消息应该被写入主题的哪个分区(键在压缩主题中也扮演了重要角色
⏱ 2025-11-20 11:42:43 ^3300044310-11-27426-27489

📌 具有相同键的消息将被写入同一个分区。
⏱ 2025-11-20 11:43:20 ^3300044310-11-27504-27522

📌 如果键为null,并且使用了默认的分区器,那么记录将被随机发送给主题的分区。
⏱ 2025-11-20 11:43:37 ^3300044310-11-28012-28050

📌 如果使用了默认的分区器,那么只有在不改变主题分区数量的情况下键与分区之间的映射才能保持一致。
⏱ 2025-11-20 11:46:53 ^3300044310-11-28766-28812

第4章 Kafka消费者——从Kafka读取数据

📌 Kafka消费者从属于消费者群组。一个群组里的消费者订阅的是同一个主题,每个消费者负责读取这个主题的部分消息。
⏱ 2025-11-21 10:08:50 ^3300044310-12-1079-1141

📌 假设主题T1有4个分区,我们创建了消费者C1,它是群组G1中唯一的消费者,用于订阅主题T1。
⏱ 2025-11-21 10:26:41 ^3300044310-12-1170-1216

📌 如果在群组G1里新增一个消费者C2,那么每个消费者将接收到两个分区的消息
⏱ 2025-11-21 10:26:49 ^3300044310-12-1538-1574

📌 如果群组G1有4个消费者,那么每个消费者将可以分配到一个分区
⏱ 2025-11-21 10:27:00 ^3300044310-12-1912-1942

📌 如果向群组里添加更多的消费者,以致超过了主题的分区数量,那么就会有一部分消费者处于空闲状态,不会接收到任何消息
⏱ 2025-11-21 10:26:54 ^3300044310-12-2246-2301

📌 除了通过增加消费者数量来横向伸缩单个应用程序,我们还经常遇到多个应用程序从同一个主题读取数据的情况。
⏱ 2025-11-21 10:42:33 ^3300044310-12-2881-2931

📌 只要保证每个应用程序都有自己的消费者群组就可以让它们获取到所有的消息。
⏱ 2025-11-21 10:42:45 ^3300044310-12-3020-3055

📌 不同于传统的消息系统,横向伸缩消费者和消费者群组并不会导致Kafka性能下降
⏱ 2025-11-21 10:43:15 ^3300044310-12-3055-3093

📌 总的来说,就是为每一个需要获取主题全部消息的应用程序创建一个消费者群组,然后向群组里添加更多的消费者来扩展读取能力和处理能力,让群组里的每个消费者只处理一部分消息。
⏱ 2025-11-21 10:48:10 ^3300044310-12-3562-3644

📌 消费者群组里的消费者共享主题分区的所有权。当一个新消费者加入群组时,它将开始读取一部分原本由其他消费者读取的消息。当一个消费者被关闭或发生崩溃时,它将离开群组,原本由它读取的分区将由群组里的其他消费者读取。主题发生变化(比如管理员添加了新分区)会导致分区重分配。
⏱ 2025-11-21 10:48:54 ^3300044310-12-3749-3880

📌 分区的所有权从一个消费者转移到另一个消费者的行为称为再均衡。再均衡非常重要,它为消费者群组带来了高可用性和伸缩性(你可以放心地添加或移除消费者)。不过,在正常情况下,我们并不希望发生再均衡。
⏱ 2025-11-21 10:49:16 ^3300044310-12-3909-4011

📌 在进行主动再均衡期间,所有消费者都会停止读取消息,放弃分区所有权,重新加入消费者群组,并获得重新分配到的分区。这样会导致整个消费者群组在一个很短的时间窗口内不可用。这个时间窗口的长短取决于消费者群组的大小和几个配置参数。从图4-6可以看到,主动再均衡包含两个不同的阶段:第一个阶段,所有消费者都放弃分区所有权;第二个阶段,消费者重新加入群组,获得重新分配到的分区,并继续读取消息。
⏱ 2025-11-21 10:49:49 ^3300044310-12-4320-4510

📌 主动再均衡会撤销分区所有权,暂停消费消息,并重新分配分区
⏱ 2025-11-21 10:50:37 ^3300044310-12-4744-4772

📌 协作再均衡(也称为增量再均衡)通常是指将一个消费者的部分分区重新分配给另一个消费者,其他消费者则继续读取没有被重新分配的分区。这种再均衡包含两个或多个阶段
⏱ 2025-11-21 10:53:11 ^3300044310-12-4852-4936

📌 这是一个无限循环。消费者实际上是一个长时间运行的应用程序,它通过持续轮询来向Kafka请求数据
⏱ 2025-11-27 09:56:22 ^3300044310-12-10755-10802

📌 4.5.1 fetch.min.bytes
这个属性指定了消费者从服务器获取记录的最小字节数,默认是1字节
⏱ 2025-11-27 10:20:38 ^3300044310-12-13007-13089

📌 4.5.2 fetch.max.wait.msopen in new window
通过设置fetch.min.bytes,可以让Kafka等到有足够多的数据时才将它们返回给消费者,feth.max.wait.ms则用于指定broker等待的时间,默认是500毫秒。
⏱ 2025-11-27 10:20:38 ^3300044310-12-13374-13518

📌 4.5.3 fetch.max.bytes
这个属性指定了Kafka返回的数据的最大字节数(默认为50 MB)
⏱ 2025-11-27 10:20:38 ^3300044310-12-13774-13858

📌 4.5.4 max.poll.records
这个属性用于控制单次调用poll()方法返回的记录条数。
⏱ 2025-11-27 10:20:38 ^3300044310-12-14166-14246

📌 4.5.5 max.partition.fetch.bytes
这个属性指定了服务器从每个分区里返回给消费者的最大字节数(默认值是1 MB
⏱ 2025-11-27 10:20:38 ^3300044310-12-14339-14437

📌 4.5.6 session.timeout.ms和heartbeat.interval.msopen in new window
session.timeout.ms指定了消费者可以在多长时间内不与服务器发生交互而仍然被认为还“活着”,默认是10秒。
⏱ 2025-11-27 10:20:39 ^3300044310-12-14703-14839

📌 heartbeat.interval.ms指定了消费者向协调器发送心跳的频率,session.timeout.ms指定了消费者可以多久不发送心跳
⏱ 2025-11-27 10:21:30 ^3300044310-12-14965-15037

📌 4.5.7 max.poll.interval.msopen in new window
这个属性指定了消费者在被认为已经“死亡”之前可以在多长时间内不发起轮询
⏱ 2025-11-27 10:28:24 ^3300044310-12-15333-15424

📌 4.5.8 default.api.timeout.msopen in new window
如果在调用消费者API时没有显式地指定超时时间,那么消费者就会在调用其他API时使用这个属性指定的值。默认值是1分钟
⏱ 2025-11-27 10:28:10 ^3300044310-12-15982-16098

📌 4.5.9 request.timeout.msopen in new window
这个属性指定了消费者在收到broker响应之前可以等待的最长时间
⏱ 2025-11-27 10:28:17 ^3300044310-12-16210-16296

📌 4.5.10 auto.offset.reset
这个属性指定了消费者在读取一个没有偏移量或偏移量无效(因消费者长时间不在线,偏移量对应的记录已经过期并被删除)的分区时该做何处理
⏱ 2025-11-27 10:28:39 ^3300044310-12-16486-16604

📌 4.5.11 enable.auto.commit
这个属性指定了消费者是否自动提交偏移量,默认值是true
⏱ 2025-11-27 10:35:36 ^3300044310-12-16827-16910

📌 PartitionAssignor根据给定的消费者和它们订阅的主题来决定哪些分区应该被分配给哪个消费者。
⏱ 2025-11-27 10:36:13 ^3300044310-12-17177-17229

📌 区间(range)
这个策略会把每一个主题的若干个连续分区分配给消费者。
⏱ 2025-11-27 10:36:26 ^3300044310-12-17279-17347

📌 轮询(roundRobin)
这个策略会把所有被订阅的主题的所有分区按顺序逐个分配给消费者。
⏱ 2025-11-27 10:36:46 ^3300044310-12-17557-17635

📌 黏性(sticky)
设计黏性分区分配器的目的有两个:一是尽可能均衡地分配分区,二是在进行再均衡时尽可能多地保留原先的分区所有权关系,减少将分区从一个消费者转移给另一个消费者所带来的开销。
⏱ 2025-11-27 10:36:54 ^3300044310-12-17822-17948

📌 协作黏性(cooperative sticky)
这个分配策略与黏性分配器一样,只是它支持协作(增量式)再均衡,在进行再均衡时消费者可以继续从没有被重新分配的分区读取消息
⏱ 2025-11-27 10:37:10 ^3300044310-12-18098-18215

📌 4.5.13 client.idopen in new window
这个属性可以是任意字符串,broker用它来标识从客户端发送过来的请求,比如获取请求。它通常被用在日志、指标和配额中。
⏱ 2025-11-27 10:51:26 ^3300044310-12-18726-18831

📌 4.5.14 client.rack
在默认情况下,消费者会从每个分区的首领副本那里获取消息。
⏱ 2025-11-27 10:52:22 ^3300044310-12-18883-18959

📌 要从最近的副本获取消息,需要设置client.rack这个参数,用于标识客户端所在的区域。
⏱ 2025-11-27 10:52:27 ^3300044310-12-19019-19064

📌 4.5.15 group.instance.idopen in new window
这个属性可以是任意具有唯一性的字符串,被用于消费者群组的固定名称。
⏱ 2025-11-27 10:52:57 ^3300044310-12-19298-19385

📌 4.5.16 receive.buffer.bytes和send.buffer.bytes
这两个属性分别指定了socket在读写数据时用到的TCP缓冲区大小。
⏱ 2025-11-27 10:53:35 ^3300044310-12-19437-19546

📌 4.5.17 offsets.retention.minutes
⏱ 2025-11-27 10:54:51 ^3300044310-12-19686-19748

📌 Kafka不像其他JMS队列系统那样需要收到来自消费者的确认,这是Kafka的一个独特之处。相反,消费者可以用Kafka来追踪已读取的消息在分区中的位置(偏移量)。
⏱ 2025-11-27 10:58:50 ^3300044310-12-20208-20290

📌 我们把更新分区当前读取位置的操作叫作偏移量提交。与传统的消息队列不同,Kafka不会提交每一条记录。相反,消费者会将已成功处理的最后一条消息提交给Kafka,并假定该消息之前的每一条消息都已成功处理。
⏱ 2025-11-27 10:59:04 ^3300044310-12-20319-20426

📌 那么消费者是如何提交偏移量的呢?消费者会向一个叫作 __consumer_offset的主题发送消息,消息里包含每个分区的偏移量。
⏱ 2025-11-27 10:59:18 ^3300044310-12-20455-20520

📌 如果最后一次提交的偏移量小于客户端处理的最后一条消息的偏移量,那么处于两个偏移量之间的消息就会被重复处理
⏱ 2025-11-27 10:59:52 ^3300044310-12-20704-20756

📌 如果最后一次提交的偏移量大于客户端处理的最后一条消息的偏移量,那么处于两个偏移量之间的消息就会丢失
⏱ 2025-11-27 10:59:46 ^3300044310-12-21043-21092

📌 所以,如何管理偏移量对客户端应用程序有很大的影响。KafkaConsumerAPI提供了多种提交偏移量的方式。
⏱ 2025-11-27 10:59:35 ^3300044310-12-21386-21441

📌 消费者API提供了一些方法,让你可以在消费者分配到新分区或旧分区被移除时执行一些代码逻辑。你所要做的就是在调用subscribe()方法时传进去一个ConsumerRebalanceListener对象。ConsumerRebalanceListener有3个需要实现的方法。
⏱ 2025-11-28 09:47:02 ^3300044310-12-29848-29986

第5章 编程式管理Kafka

📌 如果一个分区的首领副本变得不可用,而其他副本没有资格成为首领(通常是因为缺少数据)​,那么这个分区将没有首领,也就不可用了。解决这个问题的一种方法是触发不彻底的首领选举,也就是选举一个本来没有资格成为首领的副本作为首领。这可能导致数据丢失——所有写入旧首领但未被复制到新首领的消息都将丢失。
⏱ 2025-12-03 14:10:02 ^3300044310-13-22917-23061

📌 AdminClient是Kafka开发工具包中一个非常有用的工具。应用程序开发人员可以用它动态创建主题,并验证主题的配置是否符合要求。SRE可以用它创建基于Kafka的工具、实现自动化或进行故障恢复。AdminClient提供了很多有用的方法,SRE可以把它看作管理Kafka的“瑞士军刀”。
⏱ 2025-12-02 10:06:07 ^3300044310-13-30119-30265

第6章 深入Kafka

📌 Kafka使用ZooKeeper维护集群的成员信息。每个broker都有一个唯一的标识符,这个标识符既可以在配置文件中指定,也可以自动生成
⏱ 2025-12-03 16:10:29 ^3300044310-14-917-986

📌 broker对应的ZooKeeper节点会在broker被关闭之后消失,但它的ID会继续存在于其他数据结构中。
⏱ 2025-12-03 21:38:40 ^3300044310-14-1441-1496

📌 控制器其实也是一个broker,只不过除了提供一般的broker功能之外,它还负责选举分区首领。集群中第一个启动的broker会通过在ZooKeeper中创建一个名为 /controller的临时节点让自己成为控制器
⏱ 2025-12-04 09:08:25 ^3300044310-14-1680-1788

📌 控制器其实也是一个broker,只不过除了提供一般的broker功能之外,它还负责选举分区首领。集群中第一个启动的broker会通过在ZooKeeper中创建一个名为 /controller的临时节点让自己成为控制器。其他broker在启动时也会尝试创建这个节点,但它们会收到“节点已存在”异常,并“意识”到控制器节点已存在,也就是说集群中已经有一个控制器了。其他broker会在控制器节点上创建ZooKeeper watch,这样就可以收到这个节点的变更通知了。我们通过这种方式来确保集群中只有一个控制器。
⏱ 2025-12-03 21:45:27 ^3300044310-14-1680-1934

📌 如果控制器被关闭或者与ZooKeeper断开连接,那么这个临时节点就会消失。控制器使用的ZooKeeper客户端没有在zookeeper.session.timeout.ms指定的时间内向ZooKeeper发送心跳是导致连接断开的原因之一
⏱ 2025-12-04 09:08:16 ^3300044310-14-1963-2082

📌 总的来说,Kafka会使用ZooKeeper的临时节点来选举控制器,并会在broker加入或退出集群时通知控制器。控制器负责在broker加入或退出集群时进行首领选举。控制器会使用epoch来避免“脑裂”。所谓的“脑裂”,就是指两个broker同时认为自己是集群当前的控制器。
⏱ 2025-12-04 09:59:05 ^3300044310-14-3306-3444

📌 2019年,Kafka社区启动了一个雄心勃勃的项目:使用基于Raft的控制器替换基于ZooKeeper的控制器。新控制器叫作KRaft,其预览版包含在Kafka 2.8中。于2021年9月发布的Kafka 3.0包含了它的第一个生产版本,Kafka集群既可以使用基于ZooKeeper的传统控制器,也可以使用KRaft。
⏱ 2025-12-04 09:59:33 ^3300044310-14-3535-3695

📌 控制器背后的核心设计思想是:Kafka本身有一个基于日志的架构,其中用户会将状态的变化表示成一个事件流。开发社区对这种表示非常熟悉——多个消费者可以通过重放事件快速赶上最新的状态。日志保留了事件之间的顺序,并能确保消费者始终沿着单个时间轴移动。新控制器架构为Kafka的元数据管理带来了同样的好处。
⏱ 2025-12-04 10:03:48 ^3300044310-14-4598-4747

📌 新架构中,控制器节点形成了一个Raft仲裁,管理着元数据事件日志。这个日志中包含了集群元数据的每一个变更。原先保存在ZooKeeper中的所有东西(比如主题、分区、ISR、配置等)都将被保存在这个日志中。
⏱ 2025-12-04 10:04:08 ^3300044310-14-4777-4879

📌 因为使用了Raft算法,所以控制器节点可以在不依赖外部系统的情况下选举首领。首领节点被称为主控制器,负责处理所有来自broker的RPC调用。跟随者控制器会从主控制器那里复制数据,并会作为主控制器的热备。因为控制器会跟踪最新的状态,所以当发生控制器故障转移时(在此期间,所有的状态都将被转移给新控制器),很快就可以完成状态的重新加载。
⏱ 2025-12-04 10:03:31 ^3300044310-14-4908-5082

第7章 可靠的数据传递

📌 如果一个副本未能在 replica.lag.time.max.msopen in new window 指定的时间内从首领复制数据或赶上首领,那么它将变成不同步副本。在Kafka 2.5.0中,这个参数的默认值从10秒增加到了30秒,以提高集群的弹性,并避免不必要的抖动。需要注意的是,这个值也会影响消费者的最大延迟——值越大,等待一条消息被写入所有副本并可被消费者读取的时间就越长,最长可达30秒。
⏱ 2025-12-17 08:45:35 ^3300044310-15-9377-9572

第8章 精确一次性语义

📌 Kafka的精确一次性语义由两个关键特性组成:幂等生产者(避免因重试导致的消息重复)和事务语义(保证流式处理应用程序中的精确一次性处理)。下面先来介绍既简单又常用的幂等生产者。
⏱ 2025-12-17 08:58:45 ^3300044310-16-968-1056

📌 如果一个操作被执行多次的结果与被执行一次相同,那么这个操作就是幂等的
⏱ 2025-12-17 09:06:34 ^3300044310-16-1148-1182

📌 如果启用了幂等生产者,那么每条消息都将包含生产者ID(PID)和序列号。我们将它们与目标主题和分区组合在一起,用于唯一标识一条消息。broker会用这些唯一标识符跟踪写入每个分区的最后5条消息。
⏱ 2025-12-17 09:09:06 ^3300044310-16-1883-1980

📌 如果broker收到之前已经收到过的消息,那么它将拒绝这条消息,并返回错误。生产者会记录这个错误,并反映在指标当中,但不抛出异常,也不触发告警
⏱ 2025-12-17 09:09:59 ^3300044310-16-2072-2143

📌 如果broker收到一个非常大的序列号该怎么办?如果broker期望消息2后面跟着消息3,但收到了消息27,那么这个时候该怎么办?在这种情况下,broker将返回“乱序”错误。如果使用了不带事务的幂等生产者,则这个错误可能会被忽略。
⏱ 2025-12-17 09:10:17 ^3300044310-16-2259-2375

📌 就像在分布式系统中一样,研究幂等生产者在故障条件下的行为会非常有趣。可以考虑以下两种情况:生产者重启和broker故障
⏱ 2025-12-17 09:12:12 ^3300044310-16-2777-2836

📌 如果启用了幂等生产者,那么生产者在重启时就会连接broker并生成生产者ID。生产者在每次初始化时都会产生一个新ID(假设没有启用事务)。
⏱ 2025-12-17 09:12:39 ^3300044310-16-2988-3057

第9章 构建数据管道

📌 Kafka为数据管道带来的主要价值在于,它可以作为数据管道各个数据阶段之间的大型缓冲区,有效解耦数据的生产者和消费者,让同一个数据源的数据可以被多个具有不同可用性需求的系统和应用程序使用。Kafka因其出色的解耦能力以及在可靠性、安全和效率方面的良好表现,非常适合用来构建数据管道。
⏱ 2025-12-18 09:59:26 ^3300044310-17-814-955

读书笔记

第1章 初识Kafka

划线评论

📌 我们把数据从源头移动到可以对它们进行分析处理的地方,然后再把得到的结果应用到实际场景中,这样才能确切地知道这些数据要告诉我们什么。 ^37992928-84y7IX4NE
- 💭 数据快速转化为业务价值

- ⏱ 2025-11-10 11:33:08

第8章 精确一次性语义

章节评论 No.1

  • ​​核心目标​​
    本章围绕“确保每条消息在 Kafka 中被 exactly-once 处理”展开,介绍了两种互补机制——幂等生产者和事务 API——以及它们在实际系统中的使用方式和局限。
    ​​幂等生产者(Idempotent Producer)​​
    通过在消息中加入生产者 ID 与序列号,让 broker 跟踪已接收的消息,避免重复写入。
    启用后,生产者端会自动重试失败请求,但对“僵尸”生产者问题仍需额外处理。
    适用场景:单一分区内需要去重,且可接受一定工程复杂度的系统。
    ​​事务(Transactions)​​
    使用两阶段提交保证跨分区的原子写入,解决“消费-处理-生产”链条中的部分成功问题。
    事务日志记录所有操作,确保崩溃或重启后状态一致。
    与幂等生产者结合,可在分区级别提供“最多一次”+“最小一次”双重保障。
    不能跨 Kafka 边界保证一致性,对外部系统需另做幂等设计。
    ​​局限与最佳实践​​
    事务开销较高,不宜在高并发、小批量场景过度使用。
    对文件系统、数据库等外部资源的更新,需配合事务或补偿日志实现最终一致性。
    建议:在需要严格去重且数据量大的情况下选幂等生产者;在需要跨分区原子写入时使用事务;两者无法覆盖的外部操作,采用发件箱/补偿模式。
    ​​章节意义​​
    通过引入幂等与事务,本章为开发者提供了在 Kafka 上构建可靠、一致系统的“组合拳”,帮助在性能与正确性之间取得平衡。
    ^37992928-85tP9pSsm
    • ⏱ 2025-12-18 09:56:27

本书评论

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.3.0