Kafka 原理和架构解析
Kafka 是由 LinkedIn 开发的一个分布式的消息系统,使用 Scala 编写,它以可水平扩展和高吞吐率而被广泛使用。Kafka 是一种分布式的,基于发布 / 订阅的消息系统。主要设计目标如下:
- 以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 TB 级以上数据也能保证常数时间复杂度的访问性能。
- 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒 100K 条以上消息的传输。
- 支持 Kafka Server 间的消息分区,及分布式消费,同时保证每个 Partition 内的消息顺序传输。
- 同时支持离线数据处理和实时数据处理。
- Scale out:支持在线水平扩展。
Kafka 架构如下所示:
一个典型的 Kafka 集群中包含若干 Producer,若干 broker,若干 Consumer Group,以及一个 Zookeeper 集群。Kafka 通过 Zookeeper 管理集群配置,选举 leader,以及在 Consumer Group 发生变化时进行 rebalance。Producer 使用 push 模式将消息发布到 broker,Consumer 使用 pull 模式从 broker 订阅并消费消息,Consumer 使用 ZooKeeper 记录 partition 消费 offset。
为什么要使用消息系统呢?
- 解耦
- 消息格式相当于同步调用里的接口设计,在保证接口不变的基础上,生产者和消费者可以独立的扩展和修改。
- broker 负责管理生产者和消费者之间的映射关系,消费者的增加和减少不需要生产者做任何改动。
- 冗余:消息未处理完成之前,会一直保存在消息系统中,避免数据丢失。
- 削峰填谷/缓冲:生产者发送消息了剧增而消费者处理能力有限时,消息队列可以起到缓冲的作用,确保生产者发送消息不阻塞,消费者不被压垮,数据还能不丢。
- 顺序保证:Kafka 保证一个 Partition 内的消息的有序性。
Kafka 是如何做到高性能的?
- 消息顺序写入磁盘:机械磁盘读写数据时,分为寻道、旋转延迟、数据传输三个步骤。随机写时每次都要寻道、旋转延迟,性能远远低于顺序写。
- Page Cache:过于频繁的大量小 I/O 操作一样会造成磁盘的瓶颈,所以 Kafka 里的数据是先写到操作系统的缓存中,再批量刷新到磁盘。
- 零拷贝:发送数据时使用系统提供的零拷贝方法 sendfile,直接从文件复制到网卡缓存中,减少了系统调用和内存拷贝。
- 批量压缩:当网络带宽是瓶颈时,可以对数据进行压缩。单条数据压缩比可能较差,多条数据一起压缩往往能有更好的压缩比。
- 分区扩展:一个 topic 的数据在存储时是按照 partition 来分区存储的,消费者在消费 partition 时是单线程拉数据的。当拉取数据成为消费瓶颈时,可以通过增加 partition 数目来提升消费速度。
资料