Kafka入门讲解

最近听了两次kafka的分享,下面结合这两次分享简单总结下。

一、涉及到的主要名词

broker:kafka集群是由多个broker组成,每个broker作为kafka集群中一个节点。

producer:生产者,主要将消息推入kafka集群中

consumer:消费者,从kafka集群中拉取消费数据

topic:消息的主题,代表一类消息

partition:topic上的物理分组,一个topic可以有多个partition,每个partition可以看作为一个有序队列

consumer group:消费者的组成,有1~多个消费者组成。

Replicas:某一个topic+partition的副本列表。
Isr( InSyncReplicas ):处于活动状态的副本列表。开始时Replicas==Isr,但随着时间推移,有一些副本同步过慢,会被踢出,过一会可能有被加进来,Isr会不断变化。
LEO:logEndOffset,对于某一个topic+partition的副本,它的本地log的最后一条日志的偏移量。
HW:HighWatermark,min(leader.leo,replicat1.leo … replicatN.leo)所有副本的最小leo,也是能够消费的最大偏移量。

Ack:Ack是产生消息时很重要的一个参数,能取 -1,0,1。主要来表示生成者生产数据时,kafka集群在什么状态下返回成功状态。

二、kafka的拓扑结构

Kafka入门讲解

    如图所示,kafka主要由三部分组成,producer、broker和consumer。由于kafka需要将状态存放于zookeeper中,故kafka集群由kafka broker和zookeeper集群构成。

    以topic和partition维度来看,broker有两种角色:leader和follower。对于每一个topic+partition,都有一个leader和多个follower,leader负责主要数据读写操作,而follower则是不断从leader同步数据。

    而对于整个kafka集群来看,有一个broker会成为controller,controller会和zk进行通信,获取整个集群的情况。kafka集群上任何的变化,如topic的增删、broker的增删等,会由zk来发现,并通知集群的controller,由controller来通知集群上的其他节点。且当kafka集群新来一个节点时,首先先与zk进行通信,查看kafka集群是否存在controller,如果存在,则将该节点成为broker,如果无,则会抢占式去成为controller。

三、消息的生产和消费过程

消息的生产:消息的生产者,等消息满足一个批次时(例如1000条消息),将消息一起推入kafka集群,会去找对应的topic下每个partition的leader,将数据写入。这里在写入时,还会传一个参数(ack)过去,标明什么情况下返回成功。

当ack=0时,只要生产者向kafka集群写入数据,就会返回成功,不管数据是否真的写入成功。

ack=1时,当时partition的leader写入成功,则集群向生产者返回写入成功。

ack=-1时,生产者先向partition的leader写入数据,当leader写入成功,由leader向follower写入数据,当follower数据都写入完成后,则返回数据写入成功。该模式下,数据的可靠性最高。

下图表示ack为1和-1时,返回给生成者的情境。

   Kafka入门讲解

消息在broker的存储:

kafka本质上是以磁盘作为介质存储数据,每个broker存储数据时,是以在磁盘上顺序写入的方式,所以其写入数据较快。由于数据存储在磁盘上,会造成磁盘不断变大情况,这里我们可以设定(log.retention.hours)数据删除日期,例如设定7天前的数据删除。

消息的消费:

消费者采取pull的方式去partition的leader上拿取数据,并自己维护一个offset值(一个连续的用于定位被追加到分区的每一个消息的***,最大值为64位的long大小)。不会同步到zookeeper上。但是为了kafka manager能够方便的监控,一般也会手动的同步到zookeeper上。这样的好处是一旦读取某个message的consumer失败了,这条message的offsite我们自己维护,我们不会+1。下次再启动的时候,还会从这个offsite开始读。这样可以做到exactly once对于数据的准确性有保证。

broker宕机情况:

Kafka之所以称之为分布式的高可用消息队列,是因为它的每个topic+partition都有多个副本,正常情况,client只从leader读写消息,但当leader宕机时,kafka会自动切换leader到新的机器上。

Broker停止时,zk会自动删除/brokers/ids/n,controller会检测到节点的删除。
如果宕机的broker只属于任何topic+partition的follower,controller的操作比较简单,只更新当前集群的存活broker列表,并发送给所有机器( UPDATE_METADATA )。
如果宕机的broker属于某个topic+partition的leader,controller会有一个重新选举的过程,从当前isr列表中重新选举一个leader,发送LEADER_AND_ISR给新的leader和follower,并且发送UPDATE_METADATA 给所有机器。
可见,如果某一topic在建立时设置的副本数为1的话,leader宕机就不可用了。
生产消息时如果ack!=-1,可能导致消息发送给leader后,follower尚未同步,此时leader宕机,消息也就丢失了。
副本数>1 且ack ==-1可以保证消息一定不丢失。