Kafka是一个分布式的基于发布/订阅模式的消息队列,主要应用于大数据实时处理领域。
消息队列的两种模式:
- 点对点模式:一对一,消费和主动拉取数据,消息收到后消息清除
消息生产者生产消息发送到Queue中,然后消息消费者从Queue中取出并且消费消息。
消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。
- 发布/订阅模式:一对多,消费者消费数据之后不会清除消息
消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。
Kafka基础架构
1 producer:向broker发送的消息的生产者客户端
2 consumer:向broker拉取消息的消费者客户端
3 consumer group:消费者组包含的每个消费者分别消费不同分区的数据,提高消息的消费能力,每个消费者组互相独立
注意:同一消费者组内消费者不能消费同一分区的数据
4 broker:即一个kafka节点
5 topic:可以理解为队列,消息的生产和消费都是围绕某个topic即主题进行的
6 partition:一个topic可以分为多个partition并存储于不同的broker上,以实现消息的分布式存储,每个partition都是一个有序的队列
7 replication:即副本,每个分区可以是若干个副本,以保证数据的容灾性,副本按层级分为一个leader和若干个follower
8 leader:producer和consumer的数据生产和消费面向leader进行
9 follower:实时同步leader的数据,leader故障时,选举一个follower为新的leader
10 offset:consumer消费时,借助offset记录当前消息的消费位置,0.9版本以前保存在zookeeper上,
0.9版本开始保存在broker内置的topic中,并分为50个分区,topic名称为:_consumer_offsets
partition中消息的存储结构
1. partition-0在逻辑上包含n个segement,每个segement包含.log和.index两个文件,用以存储消息
2. index和.log文件以当前segement的第一条消息的offset命名
3. index文件记录了当前segement包含消息的索引,并对应当前每条消息在.log中的起始字节位置
4. log文件将每条消息有序的追加在文件内
消费者组消费消息的分区分配策略
1. round_robin(轮询)
for(分区){
for(消费者组){
//轮询分区分配给消费者组里的每个消费者
}
}
2. range(默认)
算法实现:
//平均每个消费可以分得的分区数,小数部分舍去
int numPartitionsPerConsumer = numPartitionsForTopic / consumersForTopic.size();
//不可被平分的分区数
int consumersWithExtraPartition = numPartitionsForTopic % consumersForTopic.size();
for (int i = 0; i < n = consumersForTopic.size(); i++) {
//所分区的范围的起始位置
int start = numPartitionsPerConsumer * i + Math.min(i, consumersWithExtraPartition);
//所分区的长度
int length = numPartitionsPerConsumer + (i + 1 > consumersWithExtraPartition ? 0 : 1);
}
副本的同步策略(producer发送消息的可靠性保证)注:副本数量不能大于节点数量否则报错
1. ack:分区对于接受到生产者的消息后的应答机制
ack=0:producer发送消息给leader后不会等待leader反馈是否已经落盘成功(有机会造成数据丢失)
ack=1:producer发送消息后仅等待leader落盘成功后则继续发送消息(有机会造成数据丢失)
ack=-1(all):producer发送消息后等待isr中的分区副本全部落盘成功(有机会造成数据重复)
- isr:in-sync replica set,即和leader保持同步的follower集合
- 如果存在follower长时间未和leader进行同步,则会被踢出isr()
- 如果leader挂掉,则会从isr中选出第一个follower作为leader,如果isr中的follower全部挂掉,kafka此时面临两种选择
一致性:等待isr中的节点有一个恢复,并选为新的leader
可用性:从isr以外的节点中选取一个follower作为新的leader
通过配置unclean.leader.election.enable=true(0.11版本之前默认,即保证可用性)
=false(保持一致性)
- osr:非官方概念,即未和leader保持同步的follower集合