Kafka角色架构
一图胜千言

名词解释
Broker:一个Kafka实例就是一个Broker,一个或者者多个Broker可以组成一个Kafka集群。Kafka Broker是Kafka的服务端。
Topic:Kafka根据Topic对消息进行归类,发布到Kafka集群的每条消息都需要指定一个Topic。
Partition:物理上的概念,一个Topic可以分为多个Partition,每个Partition内部是有序的。
Producer:消息生产客户端,向Broker发送消。
Consumer:消息消费客户端,从Broker读取消息。
ConsumerGroup:逻辑上的概念,每个Consumer属于一个特定的Consumer Group,一条消息可以发送到多个不同的Consumer Group,但是一个Consumer Group中只能有一个Consumer能够消费该消息。
消费模型
消息由生产者发送到kafka集群后,会被消费者消费。一般来说我们的消费模型有两种:推送模型(psuh)和拉取模型(pull)
基于推送模型的消息系统,由Broker记录消费状态。Broker将消息推送到Consumer后,标记这条消息为已经被消费,但是这种方式无法很好地保证消费的解决语义。比方当我们把已经把消息发送给Consumer之后,因为Consumer进程挂掉或者者因为网络原因Consumer没有收到这条消息,假如我们在Broker端将其标记为已消费,这个消息就永久丢失了。假如我们使用Consumer收到消息后回复这种方法,Broker需要记录消费状态,这种不可取。假如采使用push,消息消费的速率就完全由Broker控制,一旦Consumer发生阻塞,就会出现问题。
Kafka采取拉取模型(poll),由Consumer控制消费速度,以及消费的进度,Consumer可以按照任意的偏移量进行消费。比方消费者可以消费已经消费过的消息进行重新消费,或者者消费最近的消息等等。
Topic和Partition
在Kafka中的每一条消息都有一个topic。一般来说在我们应使用中产生不同类型的数据,都可以设置不同的主题。一个主题一般会有多个消息的订阅者,当生产者发布消息到某个主题时,订阅了这个主题的消费者都可以拉取到生产者写入的新消息。
kafka为每个topic维护了分布式的分区(partition)日志文件,每个partition在kafka存储层面是append log。任何发布到此partition的消息都会被追加到log文件的尾部,在分区中的每条消息都会按照时间顺序分配到一个单调递增的顺序编号,也就是我们的offset,offset是一个long型的数字,我们通过这个offset可以确定一条在该partition下的唯一消息。消息在一个partition中是保证了有序性的,但是在topic的多个partition中是没有有序性的。

在上图中我们的生产者会决定发送到哪个Partition:
1、假如没有Key值则进行轮询发送。
2、假如有Key值,对Key值进行Hash,而后对分区数量取余,保证了同一个Key值的会被路由到同一个分区,假如想队列的强顺序一致性,可以让所有的消息都设置为同一个Key。
3、可以通过实现org.apache.kafka.clients.producer.Partitioner接口自定义分区策略。
Consumer和Partition
多个Consumer组成一个ConsumerGroup,一个Consumer只能属于一个ConsumerGroup,即ConsumerGroup和Consumer是一对多的关系。一个Partition中的消息只能被ConsumerGroup中的一个Consumer消费,如果ConsumerGroup中Consumer的数量比Partition的数量多,则会有Consumer由于分不到Partition而空闲。如果ConsumerGroup中Consumer的数量比Partition的数量少,则按照Round-Robbin的方式将Partition分配给Consumer,一个Consumer可能会消费多个Partition。
Partition和Replica
kafka每个Topic的每个Partition都有一个主Partition(即Leader)以及0个或者者多个Replica,Replica保持和主Partition的数据同步,当主Partition出故障时,会选举Replica升级成为主Partition。在Kafka中,主Partition所在节点承担着所有针对该Partition的读写请求,Replica只负责数据同步。

在Kafka集群中,每个主Partition维护着一个ISR(In-Sync Replicas)集合,翻译过来也叫正在同步中集合,在这个集合中的Replica需要满足两个条件:
1、所在节点必需和ZooKeeper保持连接。
2、在同步的过程中这个Replica不能落后主Partition太多。
很显然,主Partition一定在ISR中。另外还有个AR(Assigned Replicas),用来标识Partition的全集。OSR(Out-of-Sync Replicas)用来表示因为落后被剔除的Replica集合。所以有公式如下:ISR = 主Partition + 没有落后太多的Replica; AR = OSR + ISR。只有在ISR中的Replica才有资格在主Partition挂了的时候参加竞选成为主Partition。