Kafka简介
- 分布式日志分发系统,可用于消息队列
- 创建背景
LinkedIn
开发,2011年贡献给Apache基金会
- 使用 Scala 编写
- 设计目标
- 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间复杂度的访问性能。
- 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100K条以上消息的传输。
- 支持Kafka Server间的消息分区,及分布式消费,同时保证每个Partition内的消息顺序传输。
- 同时支持离线数据处理和实时数据处理。
- Scale out:支持在线水平扩展。
- 和常用MQ对比
- 吞吐快
- 与ZooKeeper配合使用
Kafka架构
Terminology
Broker
Kafka物理机器节点,一个Kafka集群包含多个Kafka Broker
Topic
消息的类别(逻辑上概念)
Partition
消息存储物理上的概念
Producer
消息生产者
Consumer
消息消费者
Consumer Group
每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)
拓扑结构
- Kafka通过Zookeeper管理集群配置,选举leader,以及在Consumer Group发生变化时进行rebalance。
- Producer使用push模式将消息发布到broker,Consumer使用pull模式从broker订阅并消费消息。
Topic & Partition
- Topic在逻辑上可以被认为是一个queue,每条消费都必须指定它的Topic
- 物理上把Topic分成一个或多个Partition,每个Partition在物理上对应一个文件夹,该文件夹下存储这个Partition的所有消息和索引文件。
- 消息文件会分成多个segment,每个segment以该segment第一条消息的offset命名并以“.kafka”为后缀。
- 索引文件标明了每个segment下包含的消息的offset范围,如下图所示。
- 在一个Partition上,每条消息都是顺序写入,因此在一个Partition上是有时序的。
Producer消息路由
通过指定key将消息发送到某个Partition。
Consumer Group
同一Topic的一条消息只能被同一个Consumer Group内的一个Consumer消费,但多个Consumer Group可同时消费这一消息。
HA
Replica 分配策略
尽量将所有的Partition均匀分配到整个集群上。
Replica分配算法如下:
- 将所有Broker(假设共n个Broker)和待分配的Partition排序
- 将第i个Partition分配到第(i mod n)个Broker上
- 将第i个Partition的第j个Replica分配到第((i + j) mode n)个Broker上
消息接受
- Producer通过ZooKeeper找到Partition的Leader,只将消息发给Leader
- Follower从Leader pull数据,在接收到数据后就立马向Leader发送ACK。(一个在性能和持久化上比较好的平衡)
- 一旦Leader收到了ISR中的所有Replica的ACK,就认为已经commit,Leader将增加HW并且向Producer发送ACK。
对于已经commit的消息,Kafka只能保证它被存于多个Replica的内存中,而不能保证它们被持久化到磁盘中,也就不能完全保证异常发生后该条消息一定能被Consumer消费。但这种场景非常少见
Leader会跟踪与其保持同步的Replica列表,该列表称为ISR(即in-sync Replica)。如果一个Follower宕机,或者落后太多,Leader将把它从ISR中移除。
Leader Election
ISR谁先连接到就是谁