Kafka

Kafka 基础知识
一、简单介绍一下Kafka
Kafka 是一个分布式、可分区、多副本、基于ZooKeeper 协调的,以发布/订阅为模式的消息队列,主要应用于大数据实时处理领域。
二、为什么需要消息队列
举例:快递小哥<-->收件人, 快递小哥-->菜鸟驿站<--收件人。
“快递小哥” 和 “收件人” 就是两个独立交互系统,菜鸟驿站就是消息队列。    

在这里插入图片描述

消息队列有4个核心优点:解耦、异步、削峰、缓冲。
1、解耦:允许你独立的扩展和修改消息队列两边的处理程序,只要确保他们遵守同样的接口约束即可。
解释:快递小哥将属于同一小区的快递统一放在一个菜鸟驿站,然后在通知收件人来店取货。这样就实现了快递小哥和收货人之间的解耦。
2、异步:消息队列提供了异步处理机制,允许用户把消息存放到消息队列,但是不立即处理它。想向消息队列中放入多少消息就放入多少消息,然后在需要的时候再去处理。
3、削峰:在访问量急剧增加的情况下,应用仍然需要继续发挥作用。但这种突发的流量并不常见。如果以能处理这类峰值访问为标准来投入资源这无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷请求崩溃。
4、缓冲:有助于控制和优化数据流经过系统的速度,生产者和消费者处理速度不一致的问题。   
三、消息队列的两种模式
1、点对点模式(一对一,消费者主动拉取数据,消息收到后消息删除)
	消息的生产者将消息发送到消息队列,消息的消费者主动拉取消息消费。消息被消费之后,消息队列中将不在存储该消息。所以消费者不可能消费到已经被消费的消息。同时对于一个消息而言,只会有一个消费者可以消费。

优点:点对点消息队列是基于拉取或者轮询的消息传送模式,消费者主动去拉取数据进行消费,拉取的频率可以有自己控制。
缺点:消息队列中是否存在消息,消费者无法感知。所以需要消费者开启额外的线程进行监控。 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U1XwFnp0-1637938654893)(C:\Users\86156\AppData\Local\YNote\data\weixinobU7Vjlm8ZJz94-Ski7f9_r4aMUU\eb6e40dc01574c9e947e2eac21bb87aa\wps1.png)]

2、发布\订阅模式(一对多,消费者消费消息之后不会清除数据)
生产者将消息发布到指定的topic中,和点对点方式不同,发布到topic 的消息会被所有的订阅者进行消费。

发布/订阅模式又分为两种:
1、消费者主动从MQ中拉取数据
2、类似订阅在公众号的形式,由up主主动推送数据给那些订阅了自己文章的人。

在这里插入图片描述

四、Kafka 基础架构
1Producer:消息的生产者,就是向Kafka Broker 发送消息的客户端。
2Consumer:消息的消费者,就是从Kafka Broker 取出消息的客户端。
3Consumer Group:消费者组,有多个消费者构成。一个消费者组是逻辑上的一个订阅者。消费者组内的每个消费者负责消费不同分区的数据。一个分区只能被一个组内消费者消费。消费者之间互不影响。
4Broker: 一台Kafka 服务器就是一个Broker。一个集群由多个Broker构成,一个Broker 可以容纳多个topic。
5Topic:可以理解为一个队列,生产者和消费者面向的都是一个topic。

6Partition: 为了实现扩展性,一个非常大的topic 可以分布到多个broker(服务器)上,一个topic 可以分为多个partition,每一个partition 都是一个有序队列。

7Replica: 为了保证集群中的某个节点发生故障,该节点的partition 不会丢失,且Kafka仍然继续工作。kafka 提供了副本机制,一个topic的每一个分区都是由若干个副本构成,一个Leader 和 若干个 Follower8Leader:每个分区多个副本的主,生产者发送消息的对象,以及消费者消费消息的对象都是leader。
9Follower: 每个分区多个副本的从,实时的从leader 中同步数据,保持和leader数据同步。当leader发生故障时,某个follower 会成为新的Leader
五、Kafka 工作流程
Kafka中的消息是以Topic进行分类的,生产者生产消息,消费者消费消息都是面向topic的。

	Topic 是一个逻辑上的概念,为了实现扩展性,一个非常大的topic 可以分布到多个broker(服务器)上,一个topic 可以分为多个partition,每一个partition 都是一个有序队列。partition 是一个物理上的概念。每一个Partition 对应一个Log文件。该Log 文件用于存储producer 实际生产的数据,生产者生产的数据会不断地追加到该Log文件的末尾,并且每条数据都会有自己的offset。
消费者组的每个消费者,都会实时的记录自己的消费到了哪个Offset,以便出错恢复时从上一次的位置继续消费。    
六、Kafka 文件存储机制
	kafka 的文件存储机制采用了:分片和索引机制。
	由于生产者生产的消息会不断地追加到Log文件的末尾,为了防止Log文件过大导致数据定位效率低。Kafka 采用了分片和索引机制。将每个Partition 分为多个Segment。每个SegMent都对应两个文件---"index文件""log文件"。
	index 文件用于存储大量的索引信息,log文件用于存储大量的数据信息。索引文件中的元数据指向"对应数据文件中消息的物理偏移量"。   
	这些文件位于一个文件夹下,文件夹的命名方式为:topic+分区号。例如,first 这个topic 有三个分区,分别是first-0,first-1,first-2
七、Kafka分区原因
	KafkaTopic分成多个分区,这样可以实现一个非常大的Topic分布在多台Broker上。
	(1)对于整个Kafka集群而言,实现了负载均衡和水平扩展。负载均衡是为了避免一个Topic上的所有数据被存放在一台服务器上;水平扩展使得整个集群可以适应任意大小的数据。
   (2)对于消费者而言,多个消费者可以从一个或者多个partition同时消费数据,提高并发度,提高了消费速度。  
八、Kafka生产者分区的原则
	我们需要将生产者producer发送的数据封装成一个ProducerRecord对象。
(1) 在指明partition 的情况下,直接将指明的值,作为Partition的值。
(2) 在没有指明Partition但是有Key的情况下,将Key的hash 值和Topic 的分区数进行取余得到Partition的值。
(3) 在既没有Partition值有没有Key值的情况下,第一次调用时随机生成一个整数(之后每次调用都在这个整数基础上递增),将这个数与Topic的分区数进行取余,得到分区值。此方法又称为轮询。    
九、生产者发送数据的工作流程
	消息的生产者作为数据的入口,生产者在将数据写入到topic某一个分区的时候,
流程如下:
   (1)首先从集群中获取分区的leader,
	 (2)然后生产者将消息发送给Leader,
   (3)之后Leader将消息写入到本地文件,
   (4)随后FollowerLeader 值主动拉取数据,
	 (5)Follower将消息写入到本地后,向Leader发送ACK,
   (6)Leader收到所有副本的ACK后向生产者发送ACK,
		 (7)如果Producer收到ACk,就会进行下一轮的发送,否则重新发送

注意点:
 生产者采用Push的方式将消息发送给Leader,每条消息都会追加到partition中,属于顺序写磁盘(顺序写磁盘的效率要比随机写磁盘的效率高,保障了kafka的吞吐率,同时再读取数据的时候读取速度也更快)
 消息写入到Leader之后,follower 会主动的去同步数据。      

在这里插入图片描述

十、生产者发送数据的可靠性保障
	为了保证生产者发送的数据,能够可靠的发送到指定的TopicKafka在生产者里面提供了消息的确认机制。通过参数 request.required.acks 来决定等待或者直接发送下一条数据。

(1)request.required.acks=0 表示Producer不等待来自服务器的任何确认,直接发送下一条数据。这种方式数据的传输效率最高,但是可靠性最低。如果Leader发生宕机,就会造成数据丢失。
(2)request.required.acks=1 表示leader将数据写入到本地文件后,不等待所有的Follower同步完成,直接向生产者发送Ack。这种情况下数据一定写入到Leader,但是并不能保证Follower 节点已经同步完成。如果Follower 还没有同步完成,Leader发送故障,就会造成数据的丢失。
(3)request.required.acks=-1 表示leader 将数据写入到本地文件后,等到所有的Follower将数据同步完成发送消息确认后,再向Producer 发送Ack.这种方式效率最低。如果Follower在同步完数据后,在向Leader 发送ACK 时,Leader发送故障可能会造成数据的重复。   
十一、Follower 副本同步策略
1、何时发送ACK: 确保有FollowerLeader 同步完成,Leader再发送ACK。这样才能保证Leader 挂掉之后,能从Follower 选举出新的Leader2、多少个Follower同步完成后发送ACK,:全部的Follower 完成同步后,才发送ACK。
优点:选举新的Leader时,容忍N台节点故障,需要N+1个副本。
缺点:网络延迟比较高
十二、ISR
	在request.required.ack=-1时,leader将消息写入到本地文件后,需要等待所有follower都同步完成之后,再向Producer 发送ack.如果有一个Follower 发生故障迟迟未向Leader同步数据,这样Leader就会一直等待下去,直到该Follower同步完成之后才会向生产者发送ACK。
Leader维护了一个动态的和其保持同步的Follower的集合,称为ISR。如果Follower 长时间的未向Leader同步数据,该Follower就会被踢出ISR。时间限制由replica.lag.time.mx 参数设定。
如果leader 发送故障,就会从ISR 中选取新的Leader.
ISR:同步副本队列
OSR:非同步副本队列
AR:全部副本

	ISR由Leader 维护,用于存储与Leader 保持同步的follower,如果超过时间阈值Follower 仍未向Leader 同步数据,就会被剔除ISR存入到OSR。新加入到FOllower也会先存放在OSR.
AR=OSR+ISR
十三、 Partition 分区故障恢复
两个基本概念:
LEO: 每一个副本的最后一个OffSET
HW:  所有副本中最小的OFFSET,这也是所有消费者能看到的最大的OFFSET

Follower 故障恢复:
当Follower 发生故障后,会被临时从ISR中剔除掉。等到Follower 恢复后,Follower 会读取磁盘中记录的上一次HW。并将本地磁盘中高于HW的部分数据截取掉。从HW 开始向Leader 同步数据,直到Follower的LEO 大于或者等于Leader的HW。表示Follower 已经追上Leader,之后将Follower重新加入到ISR。

Leader 故障恢复:
当Leader 发生故障后,会从ISR中选取一个新的Leader。为了保证数据的一致性,在选举新的leader 后,其余的Follower 会将各自文件中高于HW 的部分数据截取掉。然后从新的Leader 中同步数据。
注意:这里只是保证了数据的一致性,并不能保证数据的不丢失和不重复。

在这里插入图片描述

十四、Exactly Once
At leader Once: 可以保证数据的不丢失,但是不能保证数据的不重复
At Most Once: 可以保证数据的不重复,但是并不能保证数据的不丢失

对于比较重要的数据而言,比如交易数据,既要保证数据的不丢失又要保证数据的不重复,因此引入Exactly Once.
0.11版本之前,kafka只能保证数据的不丢失,但是不能保证数据的不重复。需要下游消费者对数据进行去重。如果下游存在多个应用的话,每一个应用都需要对数据进行单独的全局去重势必回对性能造成极大影响。
	在0.11版本之后,Kafka 引入了幂等性。所谓的幂等性就是指无论生产者给服务器发送多少条重复数据,服务器只会持久化一条消息。幂等性结合At Least Once 就构成了 KafkaExactly once。
  Exactly Once = At Least Once +幂等性。
要启用幂等性只需要将Producer 中的 enable.idompotence设置为  true即可       
十五、kafka 如何实现幂等性
	为了实现幂等性,Kafka 引入了两个新的概念:ProducerIdSequenceNumber
	ProducerID: 每个生产者在初始化的时候,都会被分配一个ProducerID。该Producer 只对客户端可见。
SequenceNumber: 因为生产者都对应一个唯一的ProducerID。因此在生产者发送数据给每一个topic 和 partition 时候都会对应一个从0开始递增的Sequence
	引入幂等性前:producer 向 Broker 发送数据。然后Broker将消息追加到流后,会给Producer 发送ACK。这是比较理想的情况。 

在这里插入图片描述

	在实际情况中,当Broker将消息追加到消息流后,给Producer 发送ACK 前,发生故障。就会触发Producer 的重传机制。这样就会造成数据的重复。

在这里插入图片描述

	引入幂等性后:Producer在给Broker 发送消息的同时,除消息体外还包含ProducerIDSequenceNumber

在这里插入图片描述

	当触发produce人的重传机制后,生产者再次发送消息。因为消息流中已经保存了相同的ProduceriDSequenceNumber。就会将该消息删除掉,只保留一条消息。 
	幂等性通过<ProducerID,SequenceNumber>来唯一的标识一条消息。只能保持单分区和单会话的Exactly Once,无法保证跨分区和跨会话的Exactly Once。

跨会话是指:当前producer 挂了之后,再次重启会产生一个新的会话,重新分配ProducerID。

跨分区是指:当Producer重启后之后,在没有指定partition 的时候,可能会被发送到一个随机的分区可能会造成数据的重复。当指定Partition 的时候,由于PID 的变化,造成同一分区的数据重复。    
十六、Kafka 的事务性
	 kafka 从0.11版本之后,引入了事务性的概念。事务可以保证KafkaExactly Once 语义基础上实现生产和消费的跨分区和跨会话。要么全部完成,要么全部失败。

	为了实现跨分区和跨会话的事务,Kafka引入了TransactionID。并将ProducerIDTransactionID 进行绑定。这样生产者在重启之后可以通过正在运行的TransactionID 获取原来的PID。

	为了管理Transaction,Kafka 还引入了一个新的组件Transaction Coordinator 事务的协调者。 (1)生产者Producer 通过和	Transaction Coordinator 进行交互获取TransactionID 的状态。(2)同时Transaction Coordinator 还负责将事务写入到Kafka 内部的Topic,这样整个服务即使重启,由于事务已经保存,从而使得事务得到恢复进而继续运行。     
事务的流程
1、查找Transaction Coordinator 事务协调者
2、获取生产者PID
	初始化PID分为两种情况:不带TransactionID和带TransactionID
  不带TransactionID:Broker 直接生成PID
  带TransactionID:这种情况下需要根据Transaction ID 获取PID,并且只能通过Transaction Coordinator 事务协调者生成,并将这种关系保存在事务日志中。
3、启动事务
  生产者通过beginTransaction来启动事务,此时事务处于准备状态。只有当生产者发送第一条消息后,事务协调者才会认为事务已经开启。  
十七、消费者消费方式
	Kafka 消费者采用Pull模式从Broker中读取数据。
Pull的优点在于:可以根据消费者的消费能力以适当的速率进行消费。
Pull的缺点在于:如果Kafka中不存在数据,消费者将陷入循环中,一直返回空的数据。针对这一点,Kafka 的消费者在消费数据的时候传入一个时长参数timeout,当前没有数据可以消费,消费者可以等待timeout时间后再进行消费。    
	Push模式:消息发送速率由Broker决定,因此很难适应消费速率不同的消费者。
Push模式的目标在于以尽可能快的速度传递消息,但这样容易造成消费者来不及处理消息。典型的就是拒绝服务和网络拥塞。    
十八、消费者分区分配策略
	一个Consumer Group 有很多个消费者,一个Topic也会有很多个Partition。这必然涉及到Partition的分配问题。即哪个Partition 由哪个Consumer 进行消费。
	Kafka有两种分区分配策略:RangeRoundRobin
Kafka 分区分配策略的触发条件:
  1、同一个Consumer Group 内新增或者减少了Consumer
  2、订阅的Topic分区发生变化
Range策略:这是Kafka 默认的分区分配策略。Range策略是针对每一个主题而言的。

1、首先将同一个主题下的分区按照序号进行排序,同时对消费者线程按照字母进行排序。
 例如:排完序的分区结果为:0123456789;
		消费者线程排完序将是 C1-0,C2-0,C2-12、然后将同一个主题下的分区总数 除以 消费者线程总数 来决定每一个消费者线程消费哪几个分区。除不尽则前面的几个消费者线程将多消费一个分区。
例如:在我们的例子中,一共有10个 分区,3个消费者线程,10/3=3,而且除不尽,那么消费者线程C1-0 将会多消费一个分区,最后的分配结果如下:433。
		C1-0 将消费0123 分区
		C2-0 将消费456分区
		C2-1 将消费789分区。 
假如我们存在11个分区,消费者线程的数量不变,最后的分区分配结果如下:4,4,3:
		C1-0 将消费0123 分区
		C2-0 将消费 4567分区
		C2-1 将消费 8910 分区
	3、如果我们有2个主题,都是10个分区,最终的分配结果如下:
  C1-0 将消费T1 主题的0123 分区以及T2 主题的0123 分区
		C2-0 将消费T1 主题的456分区以及T2 主题的456分区
		C2-1 将消费T1 主题的789分区以及T2 主题的789 分区 

由此发现,Range策略存在一个明显的弊端,就是排序后越靠前的消费者线程可能消费越多的分区数。         
RoundRobin 策略
使用RoundRobin 策略有两个前提条件:
		 (1)同一个消费者组内的消费者线程数必须相等(nums.stream)
        (2)每一个消费者订阅的主题必须相同 
原理:首先将所有主题的分区组成一个TopicAndPartition列表,然后对TopicAndPartition 列表按照HashCode进行排序。同时对消费者线程按照字母进行排序。最后按照轮询的方式将分区分配给不同的消费者。
例如:topicAndPartition 列表按照hashcode 排序后的结果为 T1-5, T1-3, T1-0, T1-8, T1-2, T1-1, T1-4, T1-7, T1-6, T1-9 。我们的消费者线程排序后为C1-0,C1-1,C2-0,C2-2.最后的分配结果为: 

  C1-0 将消费 T1-5,T1-2,T1-6 分区。
	C1-1 将消费T1-3,T1-1,T1-9 分区。
	C2-0 将消费T1-0,T1-4 分区。
	C2-1 将消费T1-8,T1-7 分区。          
十九、消费者offset 的存储和管理
Kafka 0.9版本以前,消费者消费的offset 存储在ZooKeeper中。这种方式存在较大的隐患。原因在于:
ZooKeeper不适合做大批量的读写操作,特别是写操作。这对于后期的水平扩展而言也是一个比较头痛的问题。如果期间ZooKeeper集群发生了变化,那么Kafka的吞吐量也将受到影响。 
0.9版本以后,Kafka 将消费的Offset存储在Kafka集群中一个名为_consumer_offset 的Topic 中。
_consumer_offset 是Kafka 内部的一个Topic,对用户而言是透明的。通常是在当有第一个消费者第一次消费Kakfa 中数据的时候自动创建。
默认分区为50个,它的副本数不受集群配置的topic副本数的限制,Broker 按照以下的规则将消费者消费的Offset 存储到对应的_consumer_offset 文件夹中。
Math.abs(“groupid”.hashCode())%groupMetadataTopicPartitionCount ; 
默 认 情 况 下groupMetadataTopicPartitionCount 有 50 个分区    
	_consumer_offset 主要保存了三类信息: Consumer Group 位移信息、 Consumer Group 的元数据信息、  TombStone 信息
(1) Consumer Group 位移信息:核心点有两个,1、只有当Consumer GroupKafka 提交位移信息时_Consumer_offset 才会写入这类消息。2、这里的Consumer 既可以是ConsumerGroup又可以是Standalone Consumer。
key为【groupid+topic+partition】, value 则为要提交的位移信息

(2Consumer Group 的元数据信息:用于存储每一个消费者组的元数据信息。只有ConSumer Group 会写入这类信息,普通的Standalone Consumer 不会写入这类信息。
Key为【版本号+groupid】,value为元数据信息,见下图
这类消息是在组进行rebalance 时写入     

在这里插入图片描述

(3) TombStone 信息或者Delete Mark 消息:这类消息只出现在源码中而不暴露给用户。这类消息和Consumer Group消息很像,Key为【版本号+groupid】,唯一的区别为消息的消息体为空。
这类消息一般是在Kafka 后台线程扫描并删除过期位移 或者 _consumer_offset 副本重新分配时写入
Consumer Offset 的留存策略:delete、compact 两者兼得。一方面_consumer_offset 会定期的对消息内容进行合并,同时也会删除过期的数据。这两种策略都保存的原因在于减少该Topic 所占用的磁盘空间
二十、Offset 提交机制
Kafka 对于Offset 的处理方式有两种:自动提交方式(默认)和手动提交方式

(1)Offset 自动提交方式
kafka 的自动提交使用过enable_auto_commit和auto_commit_interval_ms 两个参数控制的。当enable_auto_commit设置为true后,kafka 在消费过程中会以频率为auto_commit_interval_ms向Kakfka 自带的topic【_consumer_offset】进行提交偏移量。
具体提交到哪一个partition 通过Math.abs(“groupid”.hashCode())%50 来计算的。

存在的问题:
(1)重复消费:当数据已经被处理,然后自动提交offset时消费者出现故障或者有新消费者加入组导致再均衡,这时候offset提交失败,导致这批已经处理的数据的信息没有记录,后续会重复消费一次。


(2)丢失数据:如果业务处理时间较长一点,这时候数据处理业务还未完成,offset信息已经提交了,但是在后续处理数据过程中程序发生了崩溃,导致这批数据未正常消费,这时候offset已经提交,消费者后续将不在消费这批数据,导致这批数据将会丢失。
2Offset 手动提交方式
手动提交偏移量有2种方式:同步、异步 组合方式。

同步:在Broker对于提交的请求做出响应之前,kafka会一直阻塞状态。直到偏移量提交成功或者提交过程发生异常。因此手动模式下同步提交将会限制消息的吞吐量。

异步:异步模式下通常采用异步加+回调的方式。消费者线程不会被阻塞,提交失败也不会进行重试。对于异步提交,由于不会进行失败重试,当消费者异常关闭或者触发再平衡前,如果偏移量还未提交就会造成偏移量的丢失。


同步+异步
这里我们采用异步+同步提交,异步提交失败后,采用同步提交,一直阻塞,达到超时时间还未提交,执行同步提交回调,可记录提交失败的数据
简单示例:
public void commitOffset() {
try {
consumer.commitAsync();//异步提交
} catch (CommitFailedException e) {
consumer.commitSync();
}
}

在这里插入图片描述

二十一、分区Rebalance
触发条件:
当有新的消费者加入消费者组、已有的消费者退出消费者组、或者订阅的主题的分区发生变化、订阅的主题数量发生变化等就会触发分区的重新分配。重新分配的过程称之为Rebalance。
消费者Rabalance之后,就会造成每一个消费者消费的分区发生变化。因此每一个消费者首先需要获取到自己被重新分配到哪一个分区,并定位该分区最近提交的offset的位置继续消费。 
Coordinator
Rebalance机制涉及一个非常重要的角色,那就是GroupCoordinator。每一个消费者组都有一个coordinator,Coordinator 负责管理组内的消费者和位移管理,并不负责消费者组内的分区分配。

消费者通过心跳的方式告知Coordinator自己仍按处于存活的状态。Coordinator 是以session.timeout.ms 参数频率检查消费者组内消费者存活状况。默认值是10s。
Rebalance流程
Coordinator 发生再平衡时,并不会主动通知组内的消费者重新入组。而是当ConsumerCoordinator 发送心跳时,Coordinator 会将Rebalance 的状况通过心跳告知ConsumerRebalance5大主要协议:入组、同步组状态、心跳、离开组、组描述请求

	1Joinning the Group:所有的消费者都会和Coordinator 进行交互,向Coordinator请求加入当前的消费者组。Coordinator 会从Consumer Group 中选取一个Consumer作为Consumer leader。

2Synchronizing Group State:Consumer 将分区的重新分配结果保障成SyncGroup。当时Leader 并不会直接和组内的消费者进行交互,而是将SyncGroup 发送给Coordinator。由Coordinator 将分配结果发送给所有的消费者。

3HeartBeat:consumer 定期向Coordinator 发送心跳表明自己存活

4LeaveGroup: consumer主动通知Coordinator自己要离开组

5DescribeGroup:仅供管理员使用,主要用于查看组的所有信息。    

分区的分配3种策略RangeAssignorRoundRobinAssignorStickyAssignor   
二十二、Kafka 高效读写数据
1、顺序写磁盘
Kafka 生产者生产的数据是要写入到log文件中。写的过程是一直追加到文件的末尾,为顺序写。官网数据表示,同样的磁盘顺序写能达到600M/s,随机写只是100k/s。这与磁盘的结构有关,顺序写之所以快,是因为省去了大量的磁头的寻址时间。
2、零拷贝技术
	在讲述零拷贝技术之前,先来看一下:传统的数据读取并传输到网络的步骤
a.首先操作系统将数据从磁盘文件中读取到内核的页面缓冲区。
b.然后应用程序将数据从内核中页面缓冲区读取到用户缓冲区。
c.之后应用程序将数据从用户缓冲区写回到内核空间的socket 缓冲区。
d.操作系统将数据从socket缓冲区复制到网卡接口,此时数据才能通过网络传输。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DAqDzoXJ-1637938654902)(C:\Users\86156\AppData\Local\YNote\data\weixinobU7Vjlm8ZJz94-Ski7f9_r4aMUU\153bc9520208410884af085531429783\clipboard.png)]

零拷贝技术
1.首先操作系统将数据从磁盘文件到复制内核空间的页面缓存一次。
2.然后直接将数据从页面缓存发送到网卡接口
3.发送给不同的消费者都使用同一的页面缓存,避免了重复的复制
传统方式和零拷贝技术的复制次数对比
对于10个消费者,传统方式数据的复制次数为4*10(4 代表了:从磁盘到页面缓存;从页面缓存到用户缓冲区;从用户缓冲区到socket 缓冲区;从socket 缓冲区到网卡接口)
零拷贝技术数据的复制次数为1+10次(1 代表从磁盘到页面缓存,10代表十个消费者各自读取一次页面缓存数据)
3、应用了PageCahce 
Page Cache是针对文件系统的缓存,通过将磁盘中的文件数据缓存到内存中,从而减少磁盘I/O操作,提高性能。
二十三、ZooKeeper在Kafka中的作用
1Broker注册
	Broker是分布式部署并且彼此之间互相独立,但是需要一个注册系统将整个集群中的Broker管理起来。此时就用到了Zookeeper,Zookeeper中存在一个专门的用来管理Broker列表记录的节点:/brokers/ids, broker会将自己的ip地址和端口信息记录到该节点中。

2Topic注册
在kafka中,一个Topic会被分成多个分区并分布到多个Broker中。这些分区信息以及与Broker的对应关系都是由Zookeeper维护的,对应的节点为/brokers/topics

3、消费者注册
消费者服务器启动的时候,会注册到对应的消费者分组。并在Zk的指定节点创建一个属于自己的消费者节点。
4、生产者负载均衡
一个Topic会被分成多个分区并分布到多个Broker中,生产者需要将消息合理的发送到这些Broker中,这就涉及到了生产者的负载均衡。
使用Zookeeper 进行负载均衡,由于Broker在启动时都会完成Broker的注册。生产者通过该结点的变化动态感知Broker列表的变化,这样就可以实现动态的负载均衡。

5、消费者负载均衡
与生产者类似,Kafka 中的消费者同样需要进行负载均衡来实现多个消费者合理的从对应的Broker 服务器上接收数据。保证每条消息都只会发送到分组中的一个消费者。
6、分区和消费者的关系
一个消费者组包含多个消费者,这些消费者共享全局唯一的GroupID。在kafka 中规定每一个消费者分区只能被同一个消费者组内的一个消费者消费。因此需要Zk来维护partition 和 consumer 的对应关系。

7、消费者消费进度
0.10以后由kafka 内置topic,_consumer_offset来维护
zookeeper 是一个分布式的协调组件,早期版本的kafka用zk做meta信息存储,consumer的消费状态,group的管理以及 offset的值。考虑到zk本身的一些因素以及整个架构较大概率存在单点问题,新版本中逐渐弱化了zookeeper的作用。新的consumer使用了kafka内部的group coordination协议,也减少了对zookeeper的依赖,

但是broker依然依赖于ZK,zookeeper 在kafka中还用来选举controller 和 检测broker是否存活等等
二十四、Kafka如何保证生产者不丢失数据,消费端不丢失数据
https://www.cnblogs.com/blazeZzz/p/9774706.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值