Kafka基本内容

一、Kafka工作流程及文件储存机制

1.工作流程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5FB49COO-1643294919766)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220127201903872.png)]

	Kafka中消息是以topic进行分类的,生产者生产消息,消费者消费消息,都面向topic
	topic是逻辑上的概念,而partition是物理上的概念,每个partition对应于一个log文件,该log文件中存储的就是producer生产的数据。Producer生产的数据会被不断追加到该log文件末端,且每条数据都有自己的offset。消费者组中的每个消费者,都会实时记录自己消费消费到了哪个offset,以便出错恢复时,从上次的位置继续消费

2.文件存储机制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N52p4FnF-1643294919768)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220127202349775.png)]

	由于生产者生产的消息会不断追加到log文件末尾,为防止log文件过大导致数据定位效率低下,Kafka采取了“分片”和“索引”机制,将每个partition氛围多个segment.每个segment对应两个文件——.index和.log,这些文件文件位于一个文件夹下。
	.index文件存储大量的索引信息,.log文件存储大量的数据,索引文件中的元数据指向对应数据文件中message的物理偏移地址

二、Kafka生产者

1.分区策略

1)分区的原因

	(1)方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了。
	(2)可以提高并发,因为可以以Partition为单位读写了。

2)分区的原则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U6ppceg2-1643294919769)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220127203506027.png)]

我们需要将producer发送的数据封装成一个ProducerRecord对象
	(1)指明partition的情况下,直接将指明的值作为partition值
	(2)没有指明partition值但有key的情况下,将key的hash值与topic的partition数进行取余得到partition值
	(3)既没有partition值又没有key值的情况下,第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与topic可用的partition总数取余得到partition值,也就是常说的round-robin算法

2.数据可靠性保证

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GKDcVc33-1643294919769)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220127203906115.png)]
为保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到producer发送的数据后,都需要向producer发送ack(acknowledgement确认收到),如果producer收到ack,就会进行下一轮的发送,否则重新发送数据

1)副本数据同步策略
方案优点缺点
半数以上完成同步,就发送ack延迟低选举新的leader时,容忍n台节点的故障,需要2n+1个副本
全部完成同步,才发送ack选举新的leader时,容忍n台节点的故障,需要n+1个副本延迟高
Kafka选择了第二种方案,原因如下:
	1.同样为了容忍n台节点的故障,第一种方案需要2n+1个副本,而第二种方案只需要n+1个副本,而Kafka的每个分区都有大量的数据,第一种方案会造成大量数据的冗余
	2.虽然第二种方案的网络延迟会比较高,但网络延迟对Kafka的影响较小
2)ISR
	采用第二种方案后,设想以下情景;leader收到数据,所有follower都开始同步数据,但有一个follower,因为某种故障,迟迟不能与leader进行同步,那leader就要一直等下去,直到它完成同步,才能发送ack,怎么解决这个问题?
	Leader维护了一个动态的ISR(in-sync-replica set),意味和leader保持同步的follower集合。当ISR中的follower完成数据的同步之后,leader就会发给follower发送ack。如果follower长时间未向leader同步数据,则该follower将被踢出ISR,该时间阈值由replica.lag.time.max.ms参数设定。Leader发送故障之后,就会从ISR中选举新的leader
3)ack应答机制

​ 对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等ISR中的follower全部接收成功。

​ 所以Kafka为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡,有如下参数选择

acks:
	0:producer不等待broker的ack,这一操作提供了一个最低的延迟,broker一接收到还没有写入磁盘就已经返回,当broker故障时有可能丢失数据
	1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果再follower同步成功之前leader故障,将丢失数据
	-1:producer等待broker的ack,partition的leadr和follower全部落盘成功后才返回ack,但是如果再follower同步完成后,broker发送ack之前,leader发送故障,那么会造成数据重复

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nnKt4tru-1643294919770)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220127210019254.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9wDEX5xv-1643294919771)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220127210028983.png)]

4)故障处理细节

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OZnlxyxp-1643294919772)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220127210126830.png)]

  • LEO:每个副本最大的offset
  • HW:消费者能见到的最大的offset,ISR队列中最小的LEO
(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文件高于HW的部分截掉,然后从新的leader同步数据(注:只能保证副本之间的数据一致性,不能保证数据不丢失或不重复)

3.Exactly Once语义

ACK = -1,保证Producer->Server之间不丢失数据,即At Least Once语义
ACK = 0,保证生产者每条消息只会被发送一次,即At Most Once语义
幂等性:Producer不论向Server发送多少次重复数据,Server端都只会持久化一条
At Least Once + 幂等性 = Exactly Once

三、Kafka消费者

1.消费方式

consumer采用push(推)、pull(拉)模式从broker中读取数据

  • push(推):很难适应消费速率不同的消费者,消息发送速率是由broker决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成comsuer来不及处理消息,典型的表现是拒绝服务以及网络拥塞。
  • pull(拉):根据consumer的消费能力以适当的速率消费消息。但如果kafka没有数据,消费者可能会陷入循环中,一直返回空数据。针对这一点,Kafka的消费者在消费数据时会传入一个时长参数timeout,如果当前没有数据可供消费,consumer会等待一段时间之后再返回,这段时长即为timeout

2.分区分配策略

​ 一个consumer group中有多个consumer,一个topic有多个partition,所以必然会涉及到partition的分配问题,即确定那个partition由哪个consumer来消费。

​ Kafka有两种分配策略,一种是RoundRobin,Range

RoundRobin:


range(按topic):

3.offset的维护

由于在consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置继续消费,所以consumer需要实时记录自己消费到哪个offset,以便故障恢复后继续消费。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kqmaLeI3-1643294919772)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220127215619253.png)]

四、Kafka高效读写数据

1)顺序读写磁盘

Kafka 的 producer 生产数据,要写入到 log 文件中,写的过程是一直追加到文件末端, 为顺序写。官网有数据表明,同样的磁盘,顺序写能到 600M/s,而随机写只有 100K/s。这 与磁盘的机械机构有关,顺序写之所以快,是因为其省去了大量磁头寻址的时间

2)零复制技术

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0JoEfLyw-1643294919773)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220127224042483.png)]

五、Zookeeper在Kafka中的作用

​ Kafka集群中有一个broker会被选举为Controller,负责管理集群broker的上下线,所有topic的分区副本分配和leader选举等工作

​ Controller的管理工作都是依赖于Zookeeper的

以下为partition的leader选举过程:

六、Kafka事务

​ Kafka 从 0.11 版本开始引入了事务支持。事务可以保证 Kafka 在 Exactly Once 语义的基 础上,生产和消费可以跨分区和会话,要么全部成功,要么全部失败

1.Producer事务

在这里插入图片描述

	为了实现跨分区跨会话的事务,需要引入一个全局唯一的Transaction ID,并将Producer获得的PID和Transaction ID绑定。这样当Producer重启后就可以通过正在进行的Transaction ID获得原来的PID
	为了管理Transaction,Kafka引入了一个新的组件Transaction Coordinator。Producer 就是通过和 Transaction Coordinator 交互获得 Transaction ID 对应的任务状态。TransactionCoordinator 还负责将事务所有写入 Kafka 的一个内部 Topic,这样即使整个服务重启,由于事务状态得到保存,进行中的事务状态可以得到恢复,从而继续进行

2.Consumer事务

​ 上述事务机制主要是从 Producer 方面考虑,对于 Consumer 而言,事务的保证就会相对 较弱,尤其时无法保证 Commit 的信息被精确消费。这是由于 Consumer 可以通过 offset 访 问任意信息,而且不同的 Segment File 生命周期不同,同一事务的消息可能会出现重启后被 删除的情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要消费其他 Kafka 服务器的内容,你需要使用 Kafka 客户端来订阅和消费消息。在 Kafka 中,消费者通过消费者组(Consumer Group)的方式来进行消息的订阅和分配。 下面是使用 Java 客户端的步骤: 1. 首先,你需要在你的项目中添加 Kafka 客户端的依赖。如果你使用 Maven,可以在 `pom.xml` 文件中添加以下依赖: ```xml <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> <version>2.8.0</version> </dependency> ``` 2. 创建 Kafka 消费者配置。配置包括 Kafka 服务器的地址和端口,以及其他可选配置项,例如消费者组 ID、自动提交偏移量等。以下是一个示例: ```java Properties props = new Properties(); props.put("bootstrap.servers", "kafka-server1:9092,kafka-server2:9092"); props.put("group.id", "my-consumer-group"); props.put("enable.auto.commit", "true"); props.put("auto.commit.interval.ms", "1000"); ``` 3. 创建 Kafka 消费者实例,并订阅需要消费的主题(topic): ```java KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props); consumer.subscribe(Arrays.asList("my-topic")); ``` 4. 开始消费消息。使用一个循环来不断地拉取和处理消息: ```java while (true) { ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100)); for (ConsumerRecord<String, String> record : records) { // 处理消息 System.out.println("Received message: " + record.value()); } } ``` 这是一个简单的示例,你可以根据实际需求进行更复杂的处理。记得在不需要时关闭消费者连接,调用 `consumer.close()` 方法。 这是使用 Kafka Java 客户端消费其他 Kafka 服务器内容基本步骤。你可以根据具体的场景和需求进行进一步的配置和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值