kafka那些事儿

295 阅读4分钟

kafka是我们熟知的一款消息队列产品。它具备高性能,持久化,支持水平扩容等特点。

kafka由三部分构成:producer broker consumer。

producer

producer是消息的生产者,将消息发送给broker。

producer消息的发送是异步的,批量的。producer端给每一个topic+partition维护了一个消息buffer。要发送的消息会先写入这个buffer,直到buffer满了或者到一定的时间,再异步发送到broker上。

broker

kafka集群的每一个节点是一个broker。

kafka中,消息是按照topic分组的。每个topic又可以分成多个partition,这些partition尽量分布在不同的broker上(当partition数量小于等于broker数量时,每个partition的broker都不同,具体可见paritition的分布策略)。同时,每个partition又有多个replica,这些replica也会尽量分布在不同的broker上(具体可见replica的分布策略)。这个原先的partition我们称为leader,而它的replica我们称为follower。producer以及consumer与broker的交互都是与leader的交互,follower的作用只是1.数据备份2.leader挂掉时被选举为新的leader。

kafka消息在partition中是顺序append的。存储消息的文件是segment。每个partition包含多个segment。每个segment都有两个文件,一个是log,记录消息;一个是index,采用的稀疏索引的方式。segment的命名是所包含消息的最小offset。通过这种方式,可以根据offset快速定位具体的消息:offset->segment->message

consumer

consumer是消息的消费者,从broker上poll消息并消费。

每个consumer隶属于一个consumer group。同一个group的全部consumer消费全部的partition,且一个partition只能被一个consumer消费。

如何保证kafka消息不丢失?

要保证kafka消息不丢失需要从三方面考虑:生产消息不丢失,存储消息不丢失,消费消息不丢失。

生产消息不丢失:

  1. producer有重试机制,可以通过retries参数进行配置;

  2. 需要将acks设置为all。ack的几种参数配置及其含义:

  3. acks=0,这种情况下producer根本不会等待broker的确认,只是负责将消息写入异步发送的本地buffer中即可。此时retries也不会生效,以为producer根本没有消息发送成功或者失败的任何结果信息。

  4. acks=1,这种情况下,只要leader节点确认消息记录成功了,就会返回成功。之后一旦leader节点挂掉,且消息也没有来得及被其它follower同步,重新选举leader后,消息也会丢失。

  5. acks=all,这种情况下,当且仅当leader节点记录下消息并且全部的follower也从leader同步完该消息才会向producer返回确认消息。从而能够保证消息不会被丢失。

存储消息不丢失:

partition具备多个replica,可以保证消息不丢失。

消费消息不丢失:

consumer端通过commit来向broker反馈自己的消费进度。如果consumer端在执行完消费逻辑之后再进行commit,则可以保证消息不丢失。反之,consumer端若poll到消息后先进行commit,再执行消费逻辑则不能保证消息不丢失。

kafka消息的三种语义:

  • exactly once
  • at most once
  • at least once

如何保证exactly once的语义?

依然要从三个角度来看:producer发送且仅发送一次,broker不丢失,consumer消费且仅消费一次。

producer发送且仅发送一次

每个producer都会有一个唯一的pid,并且为每一个<topic,partition>维护了一个单调递增的seq。同时,broker上也为<pid,topic,partition>维护了这个seq。通过这个seq,生产过程保证了exactly once的语义。若producer.seq=broker.seq+1,接受消息;若producer.seq<broker.seq+1,说明消息已经存在,丢弃;若producer.seq>broker.seq+1,说明消息跳过,丢弃。

broker消息不丢失

consumer消费且仅消费一次

一般是通过consumer端at least once+消费逻辑幂等性来实现。即先消费,后commit,同时保证消费逻辑的幂等性。幂等性的意思是消费一次与消费多次的结果一致。

什么是kafka事务?

TODO

kafka高性能的原因:TODO

  1. 顺序写
  2. 多partition,分布式,可水平扩容
  3. 零拷贝
  4. 页缓存

参考资料:

kafka 中文文档