Kafka深入
———学习尚硅谷Kafka课程视频笔记
1、Kafka工作流程
1.1、结构
生产者生产的消息还会不断追加到log的末尾,如果log文件过大,则会导致数据定位效率低下。
因此,Kafka有了分片和索引机制
一个partition对应多个Segment。一个Segment有一个index和一个log文件,这些文件位于一个文件夹下。
1.2、工作流程
Kafka的消息以topic分类。
topic是一个逻辑上的概念,log文件是实际产物。
- 生产者生产的数据会不断追加到log文件末尾,每条数据都有自己的offset
- 消费者消费数据时会实时记录消费到了哪个offset,如果出错可以从上次的位置继续消费
1.3、通过offset查询消息
.index存储着索引信息,.log文件存储着实际数据
先从.index文件中找到对应的offset,然后查询到offset = n的数据偏移量,然后根据偏移量从log文件中查询消息
2、生产者
2.1、分区
2.1.1、分区优点
- 方便扩展:多个partition可以放在不同的服务器上,方便扩容
- 提高并发:多个partition可以由一个消费者组内的多个消费者消费,提高并发,不过消费者核数要同步提高。不然分区无意义
2.2、数据可靠性
- 这里的数据可靠性是指 producer ——> topic
- producer发送的数据如果到达指定topic,topic的每个partition收到producer发送的数据且落盘之后,都要向producer发送ack来确认收到
- 如果producer收到ack,才会继续发送下一轮数据,否则重新发送数据
2.2.1、什么时候发送ack
当有follower与leader同步完成之后,leader再发送ack,这样如果leader挂了,也能立即选举出新的leader
2.2.2、多少个副本同步完成之后发送ack
两种方案:
- 半数以上同步完成之后发送
- 全部完成之后发送
Kafka选择了第二种方案,原因如下:
当选举新的leader时:
- 同样为了容忍n台节点的故障,第一种方案需要2n+1个副本,而第二种方案只需要n+1个副本,而Kafka的每个分区都有大量的数据,第一种方案会造成大量数据的冗余。
- 虽然第二种方案的网络延迟会比较高,但网络延迟对Kafka的影响较小。
2.2.3、ISR同步队列
如果采用了第二中方案,一旦有一个follower挂了,在同步数据时,leader就要一直等待故障的follower回应,这是有问题的
因此Kafka采用了ISR同步集合,只有能跟的上leader同步速度的follower才能进入ISR集合中,一旦超时就会被剔除出ISR集合中。
leader发生故障之后,会从ISR中选举新的leader
2.2.4、ack的值
有一些数据可靠性要求不高,不需要等待所有的follower同步完成,因此Kafka提供了如下几个选择
-
ack = 0 :producer不需要收到broker发送的ack即可发送下一轮数据,数据可靠性无法保证
-
ack = 1:只要producer收到 **leader落盘 ** 然后回复的 ack 就发送下一轮数据(最常用),如果副本同步完成之前,leader挂了,那么数据丢失
-
ack = -1:需要partition的 leader 和所有的 follower都返回ack才会开始下一轮发送(金融选择)
如果follower同步完成,broker发送ack之前,leader挂了,
producer会重新发送数据,这时会发生数据重复
2.2.5、故障处理流程
(1)、名词
- LEO:每个副本最后一个offset。
- HW:所有副本中最小的LEO
- HW之前的数据才能被consumer消费
(2)、follower故障
-
上面说了,只有能跟得上leader同步速度的follower才能进入ISR同步集合,如果follower挂了,那么久先被踢出ISR集合中。
-
如果该follower恢复了,follower会读取本地磁盘记录上次的HW,然后将自己的log文件中大于HW的数据删除,从上次的HW开始向leader同步。
-
当follower的LEO大于等于该paritition的HW时,follower能跟得上Leader的同步速度即可重新进入ISR集合
(3)、leader故障
- leader发生了故障,会从ISR中选出一个新的leader
- 为了保障数据一致性,其余的follower会先将各自的log文件高于HW的部分删除,然后从新的leader同步数据。
- 但是数据丢失和数据重复仍有可能发生
2.3、Exactly Once 语义
- At Least Once:ACK = -1,可以保证Producer到Server之间不丢数据
- At Most Once:ACK = 0,可以保证生产者每条数据只发送一次,保证数据不重复
有一些很重要的数据,要求不丢失也不能重复(Exactly Once)语义。
2.4、幂等性
2.4.1、解释:
幂等性 f(f(x)) = f(x),一件事不管干多少次结果都是一样的。
Kafka里面的幂等性是指:Producer不论向Server发送多少条数据,Server端都只会持久化一条。
与ACK = -1(At Least Once)一起用就构成了Exactly Once语义。
2.4.2、幂等性使用
启用幂等性:将producer的参数enable.idompotence设置为true.
2.4.3、幂等性原理
开启幂等性的producer会被分配一个PID,发往同一个Partition的消息会附带Sequence Number,而Broker端会对<PID,Partition,SeqNumber>做缓存,具有相同逐渐的消息提交时,Broker只持久化一条数据
不同的Partition具有不同主键,幂等性无法保证跨分区的Exactly Once
3、消费者
3.1、消费方式
consumer主动从broker中拉取数据,根据consumer的消费能力以适当的速度消费
如果Kafka中没有数据,Kafka的消费者在消费数据是会传入一个时长参数timeout,如果当前没有数据可以消费,consumer会等待一段时间再过来,这段时长即为timeout
3.2、分区分配策略
一个topic被一个consumer group消费,一个topic有多个partition,一个CG有多个consumer,这就要考虑一下怎么分配分区了
Kafka有两种分区分配策略
(1)range(默认)策略
如果一个topic中有十个partition,一个CG有三个consumer(0,1,2)
那么consumer-0会被分配四个partition,其余各三个。
range容易造成数据倾斜
(2)round robin
类似于斗地主发牌,轮询发往各个consumer
3.3、offset维护
0.9之前,consumer将offset保存在zookeeper中,
但是,0.9之后,consumer将offset 保存在自己 内置的一个topic 中,该topic为**_consumer_offsets**
3.4、Kafka高效读写
(1)、顺序写磁盘
producer生产数据写入到磁盘时,是一直往文件末端追加的过程,顺序写入,省去了寻址时间
(3)、零拷贝技术
linux应用系统是分层的
一般我们文件,是要从用户层调用内核,先将数据读取到内核中缓存,然后再到用户应用层,然后再到内核,再写出,就很麻烦。
Kafka直接从内核写出,不需要经过应用层
3.5、Zookeeper在Kafka中的作用
Kafka集群中的一个broker会被选举为Controller,负责管理集群broker的上下线,
所有topic的分区副本分配工作和leader选举工作
Controller的管理工作都是依赖于zookeeper的
3.6、副本leader的选举过程
- 集群启动,zookeeper中注册broker信息(brokerId)
- Kafka的Controller监听zookeeper中broker的信息
- 选举出一个leader,zookeeper中注册leader和ISR的信息
- leader的broker宕机,zookeeper更新broker信息,Controller监听
- Controller从zookeeper中获取ISR信息,并选举出一个新的leader,然后更新zookeeper中的leader和ISR信息
如有错误,还望大佬指出,第一时间修改