Kafka解析

![][0]

1 kafka 入门

消息系统:作为消息系统的队列模式(点对点模式)和发布-订阅模式
存储系统:同步阻塞发发送消息,等待消息完全地复制到多个节点,才认为这条消息发送成功
流处理系统:提供实时的流式数据处理能力:处理乱序、迟来的数据、重新处理输入数据、窗口和状态操作等

四种核心 API:生产者、消费者、连接器、流处理

1.2 基本概念

1.2.1

每个主题(Topic)有多个分区(partition),每个消息入根据不同的 Topic 均匀的分散在其中的分区中,其中入分区的每个消息都带有一个自增的偏移量,分区通过偏移量(offset)来标识消费/写进度

通过消费相同分区的消息,来保证有序性

1.2.2 消费模型

推模型:由消息中心 Broker 推送消息到消费者,缺点在于,Broker 需要记录消息已发送/已消费/未消费状态值
拉模型:由消费者自己从消息中心 Broker 拉消息,这也是 kafka 选择的模式

kafka 保存所有消息,无论是否消费。这样消费者可以根据偏移量重复消费之前的消息,或者跳着消费,缺点在于磁盘占用空间大,需要合理的设置消息清理时间,kafka 两天清理一次

1.2.3 分布式模型

消息中心,即 Broker 作为服务端,而生产者和消费者作为客户端
Broker 主节点用于处理客户端们的消息读写,而 Broker 副节点用于消息的冗余,即为最小单位 partition 分区保证完整性,而采用分布式存储,主副节点支持故障转移

消费者组支持纵向扩展,增加某个 Topic 消息吞吐量

1.3 Kafka 的设计与实现

1.3.1 文件系统的持久化与数据传输效率

预读:提前将一个比较大的磁盘块读入内存
后写:将很多小的逻辑写操作合并起来组合成一个大的物理写操作
磁盘缓存:将主内存剩余的所有空闲内存空间作为磁盘缓存,用于磁盘读写操作前的缓存
因此,在某些情况下,磁盘顺序读写比随机内存读写快

正常写入磁盘都是,先用应用程序写入内存,然后刷新到磁盘。但是 kafka 先存入磁盘缓存,然后刷新到磁盘(这不一样么,磁盘缓存在某种角度来说也是内存。。。)

传统数据复制方案:操作系统将数据从磁盘读到内核空间的页面缓存->应用程序将数据从内核空间读到用户空间的缓存区->应用程序将数据从用户空间写回内核空间的 socket 缓存区->操作系统将数据从 socket 缓存区复制到王卡卡接口,通过网络发送出去

kafka 的零拷贝方案:操作系统将数据从磁盘读到内核空间的页面缓存区->操作系统将数据直接通过网卡接口通过网络发送出去

10 个消费者情况下,传统方案,需要 10 * 4 = 40 次
零拷贝方案需要 10 + 1 = 11 次,其中的 1 次为从磁盘到内核空间的页面缓存

1.3.2 生产者与消费者

生产者采用一种”在100ms内消息大小达到64字节要立即发送,如果在100ms时还没达到64字节,也要把已经收集的消息发送出去“,通过这种缓存机制,降低延迟以换取吞吐量

消费者记录分区消费状态,好处在于消费者可以重新消费之前的消费。而消费状态是通过消费进度检查点文件实现,即在这个点之前的消息都已经被消费
消费者拉模型的缺点在于,如果消息中心(Broker)没有消息,而消费者还是继续处于一种轮询阻塞的方式请求。解决方法在于:消费者请求 Broker 时,通过消费者设置的”最低消费字节数“来判断 Broker 消息是否足够,从而是否立即返回或继续阻塞

1.3.3 副本机制和容错处理

每个 partition 在同一个节点上,可能为主,也有可能为从

为了避免数据热点问题(主数据全在一个机器上),尽量保证每个节点作为不同 partition 的主或从

副节点与主节点通信方式和客户端与主节点通信类似,只不过副节点将消息持久化,而客户端是将消息消费
副节点正在同步中(in-sync)状态:1. 副节点与 zk 连接。2. 消息复制进度不能落后太多

如何保证消息被消费者看到后,消息是真实存在磁盘中的:生产者发送消息提交到主节点,只有当副节点从主节点复制完消息后,该消息才会被消费者可见,这就是消息提交机制