元数据

深入理解Kafka:核心设计与实践原理

  •  深入理解Kafka:核心设计与实践原理|200
  • 书名: 深入理解Kafka:核心设计与实践原理
  • 作者: 朱忠华
  • 简介: 本书从Kafka的基础概念切入,循序渐进地转入对其内部原理的剖析。本书主要阐述了Kafka中生产者客户端、消费者客户端、主题与分区、日志存储、原理解析、监控管理、应用扩展及流式计算等内容。虽然Kafka的内核使用Scala语言编写,但本书基本以Java语言作为主要的示例语言,方便大多数读者的理解。虽然本书没有明确的界定,但总体上可以划分为三个部分:基础篇、原理篇和扩展篇,前4章为基础篇,包括基础概念、生产者、消费者,以及主题与分区,学习完这4章的内容完全可以应对绝大多数的开发场景。第5章至第8章为原理篇,包括对日志存储、协议设计、控制器、组协调器、事务、一致性、可靠性等内容的探究,学习完这4章的内容可以让读者对Kafka有一个深刻的认知。最后4章从应用扩展层面来做讲解,可以归类为扩展篇,主要内容包括监控、应用工具、应用扩展(延时队列、重试队列、死信队列、消息轨迹等)、与Spark的集成等,让读者可以对Kafka的生态有一个更加全面的认知。本
  • 出版时间 2019-01-01 00:00:00
  • ISBN: 9787121359026
  • 分类: 计算机-编程设计
  • 出版社: 电子工业出版社

高亮划线

1.1 基本概念

  • 📌 ZooKeeper是Kafka用来负责集群元数据的管理、控制器的选举等操作的。Producer将消息发送到Broker,Broker负责将收到的消息存储到磁盘中,而Consumer负责从Broker订阅并消费消息。

    • ⏱ 2021-10-14 08:45:35
  • 📌 Broker:服务代理节点。对于Kafka而言,Broker可以简单地看作一个独立的Kafka服务节点或Kafka服务实例。大多数情况下也可以将Broker看作一台Kafka服务器,前提是这台服务器上只部署了一个Kafka实例。一个或多个Broker组成了一个Kafka集群。一般而言,我们更习惯使用首字母小写的broker来表示服务代理节点。

    • ⏱ 2022-02-19 23:20:26
  • 📌 消息以主题为单位进行归类,生产者负责将消息发送到特定的主题

    • ⏱ 2021-10-14 08:45:36
  • 📌 逻辑上的概念

    • ⏱ 2022-02-19 23:20:47
  • 📌 一个分区只属于单个主题

    • ⏱ 2022-02-19 23:21:53
  • 📌 同一主题下的不同分区包含的消息是不同的

    • ⏱ 2022-02-19 23:22:07
  • 📌 offset是消息在分区中的唯一标识,Kafka通过它来保证消息在分区内的顺序性

    • ⏱ 2021-10-14 08:45:34
  • 📌 Kafka保证的是分区有序而不是主题有序。

    • ⏱ 2021-10-14 08:45:32
  • 📌 分区可以分布在不同的服务器

    • ⏱ 2022-02-19 23:23:26
  • 📌 一个主题可以横跨多个broker

    • ⏱ 2022-02-19 23:23:31
  • 📌 如果一个主题只对应一个文件,那么这个文件所在的机器 I/O 将会成为这个主题的性能瓶颈,而分区解决了这个问题

    • ⏱ 2022-02-19 23:24:02
  • 📌 多副本

    • ⏱ 2021-10-14 08:45:35
  • 📌 生产者和消费者只与leader副本进行交互,而follower副本只负责消息的同步,

    • ⏱ 2021-10-14 08:45:33
  • 📌 Kafka 消费端也具备一定的容灾能力

    • ⏱ 2022-02-19 23:27:03
  • 📌 消费者宕机后恢复上线时可以根据之前保存的消费位置重新拉取需要的消息进行消费,这样就不会造成消息丢失

    • ⏱ 2022-02-19 23:27:25
  • 📌 所有副本统称为AR

    • ⏱ 2022-02-19 23:27:36
  • 📌 所有与leader副本保持一定程度同步的副本(包括leader副本在内)组成ISR(In-Sync Replicas)

    • ⏱ 2022-02-19 23:27:48
  • 📌 在正常情况下,所有的 follower 副本都应该与leader 副本保持一定程度的同步,即 AR=ISR,OSR集合为空。

    • ⏱ 2022-02-19 23:28:13
  • 📌 只有在ISR集合中的副本才有资格被选举为新的leader

    • ⏱ 2022-02-19 23:28:33
  • 📌 它标识了一个特定的消息偏移量(offset),消费者只能拉取到这个offset之前的消息

    • ⏱ 2022-02-19 23:28:56
  • 📌 日志文件的HW为6,表示消费者只能拉取到offset在0至5之间的消息

    • ⏱ 2022-02-19 23:29:23
  • 📌 它标识当前日志文件中下一条待写入消息的offset

    • ⏱ 2022-02-19 23:29:50
  • 📌 如此leader副本的LEO为5,follower1的LEO为5,follower2的LEO为4

    • ⏱ 2022-02-19 23:34:41
  • 📌 那么当前分区的HW取最小值4

    • ⏱ 2022-02-19 23:34:55
  • 📌 同步复制要求所有能工作的 follower 副本都复制完,这条消息才会被确认为已成功提交,这种复制方式极大地影响了性能。而在异步复制方式下,follower副本异步地从leader副本中复制数据,数据只要被leader副本写入就被认为已经成功提交。在这种情况下,如果follower副本都还没有复制完而落后于leader副本,突然leader副本宕机,则会造成数据丢失。

    • ⏱ 2021-10-14 08:45:33

1.4 服务端参数配置

  • 📌 server.properties

    • ⏱ 2022-02-19 23:55:52
  • 📌 broker要连接的ZooKeeper集群的服务地址

    • ⏱ 2022-02-19 23:56:01
  • 📌 broker监听客户端连接的地址列表

    • ⏱ 2022-02-19 23:57:12
  • 📌 该参数用来指定Kafka集群中broker的唯一标识,默认值为-1

    • ⏱ 2022-02-19 23:58:02
  • 📌 该参数用来指定broker所能接收消息的最大值,默认值为1000012(B),约等于976.6KB

    • ⏱ 2022-02-19 23:58:21

2.1 客户端开发

  • 📌 消息对象 ProducerRecord

    • ⏱ 2022-02-20 00:04:58
  • 📌 key是用来指定消息的键,它不仅是消息的附加信息,还可以用来计算分区号进而可以让消息发往特定的分区

    • ⏱ 2022-02-20 00:06:49
  • 📌 value是指消息体,一般不为空,如果为空则表示特定的消息—墓碑消息

    • ⏱ 2022-02-20 00:07:10
  • 📌 KafkaProducer是线程安全的,可以在多个线程中共享单个KafkaProducer实例,也可以将KafkaProducer实例进行池化来供其他线程调用。

    • ⏱ 2022-02-20 00:11:28
  • 📌 构建消息,即创建ProducerRecord对象

    • ⏱ 2022-02-20 00:13:42
  • 📌 其中topic属性和value属性是必填项

    • ⏱ 2022-02-20 00:13:53
  • 📌 。发送消息主要有三种模式:发后即忘(fire-and-forget)、同步(sync)及异步(async)

    • ⏱ 2022-02-20 00:17:59
  • 📌 它只管往Kafka中发送消息而并不关心消息是否正确到达

    • ⏱ 2022-02-20 00:18:07
  • 📌 实际上send()方法本身就是异步的,send()方法返回的Future对象可以使调用方稍后获得发送的结果。

    • ⏱ 2022-02-20 00:20:03
  • 📌 这样可以获取一个RecordMetadata对象,在RecordMetadata对象里包含了消息的一些元数据信息,比如当前消息的主题、分区号、分区中的偏移量(offset)、时间戳等

    • ⏱ 2022-02-20 00:26:29
  • 📌 LeaderNotAvailableException表示分区的leader副本不可用,这个异常通常发生在leader副本下线而新的 leader 副本选举完成之前,重试之后可以重新恢复

    • ⏱ 2022-02-20 00:27:02
  • 📌 暗示了所发送的消息太大,KafkaProducer对此不会进行任何重试,直接抛出异常。

    • ⏱ 2022-02-20 00:27:11
  • 📌 Kafka有响应时就会回调,要么发送成功,要么抛出异常

    • ⏱ 2022-02-20 00:29:28
  • 📌 对于同一个分区而言,如果消息record1于record2之前先发送(参考上面的示例代码),那么KafkaProducer就可以保证对应的callback1在callback2之前调用,也就是说,回调函数的调用也可以保证分区有序。

    • ⏱ 2021-11-30 08:44:18
  • 📌 close()方法会阻塞等待之前所有的发送请求完成后再关闭KafkaProduce

    • ⏱ 2022-02-20 00:38:44
  • 📌 生产者需要用序列化器(Serializer)把对象转换成字节数组才能通过网络发送给Kafka。而在对侧,消费者需要用反序列化器(Deserializer)把从 Kafka 中收到的字节数组转换成相应的对象

    • ⏱ 2022-02-20 00:39:19
  • 📌 生产者使用的序列化器和消费者使用的反序列化器是需要一一对应的

    • ⏱ 2022-02-20 16:42:16

读书笔记

1.1 基本概念

划线评论

  • 📌 leader副本负责处理读写请求,follower副本只负责与leader副本的消息同步
    • 💭 所以follower不对外提供读写服务
    • ⏱ 2022-02-19 23:25:41

划线评论

  • 📌 分区
    • 💭 topic是逻辑概念,partition则是有物理存储结构的(文件夹)
    • ⏱ 2022-02-19 23:21:44

2.1 客户端开发

划线评论

  • 📌 只不过Future里的 get()方法在何时调用,以及怎么调用都是需要面对的问题,消息不停地发送,那么诸多消息对应的Future对象的处理难免会引起代码处理逻辑的混乱
    • 💭 send本身就是异步的,不直接使用send来回调的原因:
    • ⏱ 2022-02-20 00:29:19

本书评论