2:kafka架构

1、kafka工作流程和文件存储机制

  • kafka中消息是以topic进行分类的,生产者生产消息,消费者消费消息都是面向topic的;
  • topic是逻辑上的概念,而partition是物理上的概念,每个partition对应一个log文件,文件中存储的就是producer生产的数据。会不断追加到文件末端,媒每条数据都有自己的offset,消费者也会记录自己消费到了哪个offset.以便出错时从上次的位置继续消费;
    2:kafka架构_第1张图片
  • 为防止log文件过大导致数据定位效率低下,kafka采取了分片和索引机制,将每个partition分为多个segment。每个segment对应两个文件:index文件和log文件,位于一个文件夹下,文件夹的命名是topic名称+分区序号。index和log文件是以当前segment的第一条消息的offset命名。

2:kafka架构_第2张图片
index文件存储大量的索引信息,log文件存储大量数据,索引文件中的元数据指向对应数据文件中的message的物理偏移地址。

2、kafka生产者

2.1 分区策略

为什么分区

方便在集群中扩展
可以提高并发:以分区为单位读写;

分区原则

将producer发送的数据封装成一个ProducerRecord对象;
2:kafka架构_第3张图片

  • 指明partition的话,直接将其作为partition值;
  • 未指定partition的话,将key的hash值%(partition数量)得到partition值;
  • 若key和partition都没有,使用round-robin算法,第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与topic的可用的分区数取余。

数据可靠性保证

为保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到数据后,需要向producer发送ack,如果producer收到ack,就会进行下一轮的发送,否则重新发送数据;
2:kafka架构_第4张图片

副本数据同步策略

方案 优点 缺点
半数以上完成同步 延迟低 选举新的leader时,容忍n台节点的故障需要2n+1个副本
全部同步完成 才发送ACK 选举新的leader时容忍n台节点的故障需要n+1个副本 延迟高

kafka使用第二种方案原因如下:

  • 为了容忍n台节点的故障,第一种方案需要2n+1个副本,第二种只需要n+1个副本,kafka的每个分区都有大量的数据,第一种方案造成大量冗余;
  • 第二种方案网络延迟较高,但是网络延迟对kafka的影响较小;

ISR(in-sync replica set)
  对于第二种情况:leader收到数据,所有follower都开始同步数据,但是有一个follower,因为某种故障,迟迟不能与leader进行同步,那么leader就要一直等下去直到完成同步才能发送ack。怎么解决呢:
leader维护了一个动态的in-sync replica set(ISR),即和leader保持同步的follower集合。当ISR中的follower完成数据的同步之后,leader给follower发送ack,若是follower长时间没有向leader发送同步数据,则该follower将会被踢出ISR。leader发生故障之后将会从ISR这选举新的leader;

ACK应答机制
对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,没必要等ISR的follower全部接收成功;
kafka为用户提供了三种可靠性级别。通过对acks参数进行配置:

  • 0:producer不等待broker的ack,这一操作提供了一个最低的延迟,broker故障时可能丢失数据;
  • 1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,将会丢失数据;
    2:kafka架构_第5张图片
  • -1(all):producer等待broker的ack,partition的leader和follower全部落盘成功后返回ack。如果在follower同步完成后,broker发送ack之前leader发生故障,会造成数据重复;
    2:kafka架构_第6张图片

故障处理细节

LEO(log end offset):每个副本的最后一个offset
HW(high watermark):所有副本中最小的LEO
2:kafka架构_第7张图片

(1)follower故障
follower发生故障后会被临时踢出ISR,待该follower恢复后,follower会读取本地磁盘记录的上次的HW,将log文件中高于HW的部分截取掉,从HW开始向leader进行同步。等该follower的LEO大于等于该partition的HW,即follower追上leader之后就可以重新加入ISR了。
(2)leader故障
leader发生故障之后,会从ISR中选出一个新的leader,其余的follower会先将各自的log文件高于H的部分截掉,从新的leader中同步数据;

exactly once语义

  • 将服务器的ACK级别设置为-1,可以保证producer到server之间不会丢失数据 即at least once语义;
  • 将服务器ACK级别设置为0,可以保证生产者每条消息只会被发送一次即At Most Once语义;
  • At Least Once可以保证数据不丢失,但是不能保证数据不重复;相对的, At Least Once可以保证数据不重复,但是不能保证数据不丢失。
  • 对于一些非常重要的信息,比如交易数据,下游数据消费者要求数据既不重复也不丢失;即Exactly once语义。在0.11版本之前对此是无能为力的,只能保证数据不丢失,再在下游消费者对数据进行全局去重。
  • 0.11版本的kafka,引入了一项重大特性:幂等性。不论producer向server发送多少次重复数据,server端只会持久化一条。
    At Least Once+幂等性=Exactly Once

3、kafka消费者

3.1 消费方式

consumer采用pull模式从broker中读取数据;

push模式的不足是:

push模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的;broker的目标是尽可能以最快的速率传递消息,很容易造成consumer来不及处理消息,造成拒绝服务以及网络阻塞。pull模式可以根据consumer的消费能力以适当的速率消费消息;

pull模式的不足:

如果kafka没有数据,消费者可能会陷入循环中,一直返回空数据。
解决:kafka消费者在消费数据时会传入一个时长参数timeout,如果当前没有数据可以消费,consumer会等待timeout后再返回;

3.2 分区分配策略

一个消费者组中有多个消费者,一个topic有多个分区,必然涉及到分区的分配问题;

kafka有两种分配策略,RoundRobin和Range:
RoundRobin
2:kafka架构_第8张图片
range
2:kafka架构_第9张图片

3.3 offset的维护

由于consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置继续消费,所以consumer需要实时记录自己消费到了哪个offset,以便故障恢复后继续消费;
kafka0.9版本之前,consumer默认将offset保存在zookeeper中,从0.9版本开始consumer默认将offset保存在kafka一个内置的topic中,该topic为__consumer_offsets。

3.4 kafka高效读写数据

顺序写磁盘
  生产者生产的数据需要写入到log文件,一致追加到文件末尾,为顺序写。官网数据表明,同样的磁盘顺序写能到600M/s,随机写只有100k/s。
零复制技术
kafka中的消费者在读取服务端的数据时,需要将服务端的磁盘文件通过网络发送到消费者进程,网络发送需要经过几种网络节点。
2:kafka架构_第10张图片
通常情况下,kafka的消息会有多个订阅者,生产者发布的消息会被不同的消费者多次消费,为了优化这个流程,kafka使用了零拷贝技术:
2:kafka架构_第11张图片
零拷贝技术只用将磁盘文件的数据复制到页面缓存一次,然后将数据从页面缓存直接发送到网络中,避免了重复复制操作。

3.5 zookeeper在kafka的作用

kafka集群中有一个broker会被选举为controller,负责管理集群broker的上下线、所有topic的分区副本分配和leader选举等工作;controller的管理工作都是依赖于zookeeper的;

你可能感兴趣的:(kafka)