Kafka 是一种 高吞吐量的、分布式的、基于 zookeeper 协调的 发布订阅消息系统,常用于 web/nginx日志、访问日志、消息服务等,Kafka 起初由 LinkedIn 公司开发,后于 2010年 贡献给 Apache 基金会 并成为 顶级开源项目。
Kafka 的特性:

相关术语:
Broker
Kafka 集群 包含 一个或多个服务器,每一个服务器 称为 一个 Broker 。
Topic
每条发布到 Kafka 集群的消息都有一个类别,这个类别被称为 Topic 。
物理上,不同 Topic 的消息 分开存储;逻辑上,一个 Topic 的消息 可以存储在 一个或者多个 Broker 中,但 用户 只需要指定消息的 Topic 即可 生产(或消费)消息,而不需要关心 消息 究竟存储在哪个 Broker 中。
Partition
每个 Topic 被物理划分为 一个或多个分区(Partition),每个分区对应着一个文件夹(存储该分区所有的消息 和 索引文件)。在创建 Topic 时可指定 Partition 的数量,生产者 将消息发送到 Topic 时,消息会根据 分区策略(决定生产者将消息发送到哪个分区的算法) 追加到 分区文件的末尾。
注:同一 Topic 的 多个 Partition 可以部署在多台机器上。

补充:自定义分区策略(常用)
用户 可以为每条消息设置一个 Key,Kafka 保证 同一个 Key 的所有消息 都能够进入到 同一个分区中(也被称为 Key-ordering 策略)。
Offset
Partition 中的每条消息都有一个序号(表示消息在 Partition 中的偏移量)称为 Offset,每条消息在同个 Partition 中的 Offset 都是唯一的,消费者 可以通过指定 Offset 来 消费 想要消费的消息。
Producer
生产者,生产消息 并 将消息发送到指定的 Topic 中。
Consumer
消费者,从 Topic 中 获取并消费 消息。
Consumer group
消费者组,每个 Consumer 都属于一个特定的 Consumer group(既可以是 默认的 group,也可以是 指定的 group)。
同一 Topic 的一条消息,只能被 同一个 Consumer group 中的一个 Consumer 消费(消息单播),但可以被 多个 Consumer group 中的多个 Consumer 同时消费(消息广播)。
Leader / Follower
每个 Partition 可能会有多个副本,但有且仅有一个作为 Leader,其余的为 Follower,Leader 负责所有客户端的读写操作,Follower 只负责同步 Leader 的数据。
当 Leader 挂掉时,会从其余的多个 Follower 中选举 一个 Follower 作为新的 Leader;当 Follower 挂掉 或 同步太慢 时,Leader 会将这个 Follower 从 ISR 列表中删除 并 重新创建一个 Follower。
Rebalance
意为 “重平衡”,当 Consumer group 中的某个消费者挂掉时,其他的消费者会 自动重新分配 订阅的主题分区,实现负载的重均衡(Kafka 消费者端 实现高可用的重要手段)。
Zookeeper 是一个 分布式应用程序 协调服务,主要负责管理 Broker 集群的上下线、所有 Topic 的分区副本分配 和 Leader 的选举等工作。
为保证 Producer 发送的消息 都能够可靠的到达指定的 Topic 中,Topic 的每个 Partition 收到消息后,都需要向 Producer 发送 ACK(acknowledgement),如果 Producer 收到了 ACK 就会进行下一轮的消息发送,否则 Producer 将 重新发送 该消息,这就是生产者 ACK 机制。
补充:ACK 参数配置
| 参数 | 说明 |
|---|---|
| 0 | Producer 不等待 Broker 的 ACK(最低延迟,但当 Broker 未将消息持久化 就发生故障时,会造成该消息的丢失) |
| 1 | Producer 等待 Broker 的 ACK,当 Leader 将消息持久化成功后,发送 ACK |
| -1 | Producer 等待 Broker 的 ACK,当 Leader 和 Follower 都将消息持久化成功后,发送 ACK |
Kafka 的消息是 保存或缓存 在磁盘上的,一般认为 在磁盘上读写数据 是会降低性能的,因为寻址会比较消耗时间,但实际上 Kafka 的特性之一就是 高吞吐率,即使是普通的服务器,Kafka 也可以轻松支持每秒百万级的写入请求。
下面分别从数据的写入和读取两方面分析,为什么 Kafka 速度这么快:
1、写入数据
顺序写入
实际上,决定 磁盘读写快慢 的关键在于 寻址方式(即采用 顺序读写 还是 随机读写),磁盘的随机读写速度确实很慢,但 磁盘的顺序读写速度却快得多(一般来说,比随机读写高出三个数量级,一些情况下甚至高于内存的随机读写)。
注:同样的磁盘,顺序写可以达到 600M/s,而随机写只有 200K/s 。
MMFile(Memory Mapped Files,内存映射文件,简称 mmap)
即使是 顺序写入磁盘,但访问速度与内存相比还是相差甚远,因此 Kafka 并不是采用将数据实时写入磁盘的方式,而是采用 mmap 方式(直接利用 OS 的 Page 实现文件到物理内存的直接映射,之后由 OS 在适当的时候将数据冲洗(flush)到磁盘中)。
Kafka 提供了一个参数(producer.type)来控制是否主动 flush,将 消息写入 mmap 后主动 flush 称为 同步(sync)冲洗,否则称为 异步(async)冲洗。
2、读取数据
基于 sendfile 的 “zero-copy” 机制
传统模式下的网络文件传输流程大致为:
使用 “zero-copy”机制的网络文件传输流程大致为:
总结:
“zero-copy”机制 并不是说 整个过程完全不发生拷贝,而是 避免了 内核空间 到 用户空间 的来回拷贝。相较于传统模式,“zero-copy”机制 既减少了 2 次 copy 的次数,同时也减少 2 次系统上下文的切换,大大提高 I/O 性能。
批量压缩
在很多情况下,系统的瓶颈 不是 CPU 或 磁盘 而是 网络 I/O,Kafka 采用 消息 批量压缩 的方式 降低了 网络 I/O 的损耗,提升了系统的性能。