目录
一:kafka主要架构
Broker:在Kafka集群中负责存储和处理数据的服务器节点。每个broker可以被分配一个唯一的broker id,并且通过设置监听端口来进行数据交互。Kafka broker与Zookeeper之间通过数据交互来维护集群的元数据信息。
Producer:生产者,向topic内生产数据
Consumer:消费者,消费topic内的数据
Topic:主题,可以理解为一个队列,生产者和消费者都面向队列
Partition:一个数据量非常大的topic可以分布在不同的broker节点上,而topic可以拥有多个分区,每个分区分区内都是有序的队列
Replica:为了保证某个partition的数据不丢失,kafka提供了副本机制,每个分区都拥有多个副本,
Leader:每个分区的多个副本的主要角色,生产者发送数据、消费者拉去数据的对象
Follower:每个分区的多个副本的次要角色,实时的从Leader中同步数据,保持和Leader数据的同步,Leader发生故障的时候,某个Follower会成为新的Leader。
也就是说,一个kafka集群中会有多个broker,而topic可以存放在多个broker中,每个topic可以拥有多个分区,每个分区拥有多个副本,副本中存在Leader和Follower.Leader为Produer和Consumer的实际交互数据的点,而Follower主要负责同步Leader的数据
二:Producer
1.kafka文件存储的格式
以一个简单的topic,分区1,副本1为例
kafka-topics.sh --create --zookeeper 192.168.10.129:2181 --topic test --partitions 1 --replication-factor 1
进入存放kafka存放topic数据的文件夹中
进入test-0文件夹中,可以看到
生产者不断的向log文件追加消息文件,为了防止log文件过大导致定位效率低下,Kafka的log文件以1G为一个分界点,当.log
文件大小超过1G的时候,此时会创建一个新的.log文件,同时为了快速定位大文件中消息位置,Kafka采取了分片和索引的机制来加速定位。
2.ISR副本同步机制
leader中维护了一个动态的ISR(in-sync replica set),即与leader保持同步的follower集合,当ISR中的follower完成数据的同步之后,给leader发送ack,如果follower长时间没有向leader同步数据,则该follower将从ISR中被踢出,该之间阈值由replica.lag.time.max.ms参数设定。当leader发生故障之后,会从ISR中选举出新的leader。
3.ACK应答机制
对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没有必要等到ISR中所有的follower全部接受成功。
Kafka为用户提供了三种可靠性级别,用户根据可靠性和延迟的要求进行权衡选择不同的配置。
ack参数配置:
0:Producer不等待broker的ack,这样子减少了延迟,但可能会导致数据丢失
1:Producer等待Leader数据落盘了再返回ack.如果数据到follower成功之前leader出现故障,则会丢失数据,此时只有leader落盘,而follower可能数据丢失
-1(All):Producer等待Leader和Follower数据都落盘后再返回ack.这样子延迟高,但是可以保证数据不会丢失,但可能会造成数据重复
4.kafka如何保证数据一致
一个kafka集群中,一个节点向不同的节点传输数据时可能会增加io的消耗,即跨节点传输.每个节点向近节点和远节点的传输效率也不同,这也造成了Leader向Follower同步数据时,可以会产生记录的偏移量不一致的情况,此时我们就引入了LEO和HW两个概念
- LEO(Log End Offset):每个副本最后的一个offset
- HW(High Watermark):高水位,指代消费者能见到的最大的offset,ISR队列中最小的LEO。
LEO记录的时每个副本最近的偏移量,而HW记录的是Leader和Follower中偏移量最小的(因为跨节点传输的原因),也就是说,HW就是LEO中的最小值
Follower或Leader故障
1.follower故障: 当一个follower故障时,会被踢出ISR,等待该follower恢复后,会读取当前的HW,并将高于HW的log文件内的数据删除,也就是说此时follower的偏移量为HW线,然后开始向leader同步,等到该follower追上leader后,就把它加入ISR,继续生产
2.leader故障:当一个leader故障后,会从ISR中选出一个新的leader,其余的作为follower.为了保证多个副本之间的数据的一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader中同步数据。
这只能保证数据的一致性,并不能保证数据不丢失或者数据不重复
三:Consumer
消费者采用pull的方式主动从broker中去拉取数据
主动拉取数据时,可以设置batch.size的大小,意思是当数据达到这个大小时,主动去拉去,一批一批的拉去,减少了一个一个拉取的性能消耗.当前如果数据量小,很长时间没有达到批处理的大小时,也可以设置一个时长参数linger.ms,当达到这个时间时,消费者会主动去拉取数据
1.消费者分区策略
(1)Round-Robin:轮询
按照分区的字典对分区和消费者进行排序,然后对分区进行循环遍历,遇到自己订阅的则消费,否则向下轮询下一个消费者。即按照分区轮询消费者,继而消息被消费.可能造成各个消费者消费的分区数量不一致,进而会出现数据倾斜等问题
(2)Range:重分配
按照消费者数量进行平均分配,多出来的会按照分区的字典挨个分配,可能会导致各个消费者间消费的分区相差一个,但不影响综合性能,这也是消费者默认的分区策略
2.消费者消费偏移量的记录
当消费者出现故障时,应当从故障前的位置进行消费,这也就涉及到了消费偏移量的问题
kafka0.9版本之前,消费者的偏移量存储在zookeeper中,0.9之后,偏移量存储在kafka的一个内置topic中,该topic为__consumer_offsets
3.消费策略
由于一条消息只能被一个消费者组的消费者消费一次,因此需要变更消费者组
在一个新的消费者组中,有三个消费策略可以消费数据
earliest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费
latest : 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的数据
none : 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,抛出异常
API可以调用ConsumerConfig.AUTO_OFFSET_RESET_CONFIG来赋值,具体可以参考Kafka入门及其原理_Natsu爱学习的博客-CSDN博客中消费者api的调用
4.消费者提交偏移量的方式
分为自动提交和手动提交
自动提交比较方便,但是由于基于时间的提交方式,难以掌控
而手动提交分为两种方式,commitSync(同步提交)和commitAsync(异步提交),两者都会将本次pull的最高偏移量提交,但是如果出现故障时,同步提交会阻塞当前进程,触发失败重试直到提交成功,而异步提交由于没有失败重试机制,可能会提交失败
5.消费漏数据或消费重复数据
无论是同步提交还是异步提交offset,都可能会造成数据的漏消费或者重复消费.
先提交offset后消费的情况,如果提交完offset后出故障,则会导致下次消费从offset+1开始消费,而当前offset实际上还没有消费,出现了漏消费的情况
先消费后提交offset的情况,如果消费完后出故障,则当前消费完的offset尚未存储,记录的仍然是消费到offset-1的情况,那么等下次开始消费时,从offset开始消费,进而造成了重复消费的情况