对 log 进行分区(partitioned),有以下目的。首先,当 log 文件大小超过系统文件系统
的限制时,可以自动拆分。每个 partition 对应的 log 都受到所在机器的文件系统大小的限
制,但是一个 Topic 中是可以有很多分区的,因此可以处理任意数量的数据。另一个方面
,是为了提高并行度。
Distribution
log 的 partitions 分布在 kafka 集群中不同的 broker 上,每个 broker 可以请求备份其他
broker 上 partition 上的数据。kafka 集群支持配置一个 partition 备份的数量。
针对每个 partition,都有一个 broker 起到“leader”的作用,0 个多个其他的 broker 作为
“follwers”的作用。leader 处理所有的针对这个 partition 的读写请求,而 followers 被动
复制 leader 的结果。如果这个 leader 失效了,其中的一个 follower 将会自动的变成新的
leader。每个 broker 都是自己所管理的 partition 的 leader,同时又是其他 broker 所管理
partitions 的 followers,kafka 通过这种方式来达到负载均衡。
Producers
生产者将消息发送到 topic 中去,同时负责选择将 message 发送到 topic 的哪一个 partition
中。通过 round-robin 做简单的负载均衡。也可以根据消息中的某一个关键字来进行区
分。通常第二种方式使用的更多。
Consumers
传统的消息传递模式有 2 种:队列( queuing)和( publish-subscribe)。
在 queuing 模式中,多个 consumer 从服务器中读取数据,消息只会到达一个 consumer。
在 publish-subscribe 模型中,消息会被广播给所有的 consumer。Kafka 基于这 2 种模式提
供了一种 consumer 的抽象概念:consumer group。
每个 consumer 都要标记自己属于哪一个 consumer group。发布到 topic 中的 message 中
message 会被传递到 consumer group 中的一个 consumer 实例。consumer 实例可以运行在
不同的进程上,也可以在不同的物理机器上。
如果所有的 consumer 都位于同一个 consumer group 下,这就类似于传统的 queue 模式,
并在众多的 consumer instance 之间进行负载均衡。
如果所有的 consumer 都有着自己唯一的 consumer group,这就类似于传统的 publish-
subscribe 模型。
更一般的情况是,通常一个 topic 会有几个 consumer group,每个 consumer group 都是一
个逻辑上的订阅者( logical subscriber )。每个 consumer group 由多个 consumer
instance 组成,从而达到可扩展和容灾的功能。这并没有什么特殊的地方,仅仅是将
publish-subscribe 模型中的运行在单个进程上的 consumers 中的 consumer 替换成一个
consumer group。如下图所示: