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消息不丢失需要从三方面考虑:生产消息不丢失,存储消息不丢失,消费消息不丢失。
生产消息不丢失:
-
producer有重试机制,可以通过retries参数进行配置;
-
需要将acks设置为all。ack的几种参数配置及其含义:
-
acks=0,这种情况下producer根本不会等待broker的确认,只是负责将消息写入异步发送的本地buffer中即可。此时retries也不会生效,以为producer根本没有消息发送成功或者失败的任何结果信息。
-
acks=1,这种情况下,只要leader节点确认消息记录成功了,就会返回成功。之后一旦leader节点挂掉,且消息也没有来得及被其它follower同步,重新选举leader后,消息也会丢失。
-
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
- 顺序写
- 多partition,分布式,可水平扩容
- 零拷贝
- 页缓存
参考资料: