Kafka学习总结(一)

一、概述

1.1、概念

Kafka 是一种分布式的基于发布/订阅模式消息队列(Message Queue),主要应用于大数据实时处理领域。

1.2、传统消息队列应用场景

1.3、使用消息队列的好处

1.3.1、解耦

允许独立的扩展或者修改两边的处理过程,只要确保它们遵守同样的接口约束。

1.3.2、可恢复性

系统的一部分组件失效时,不会影响到整个系统,消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列的消息仍然可以在系统恢复后被处理。

1.3.3、缓冲

有助于控制和优化数据经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。

1.3.4、灵活性 和 削峰处理能力

在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见,如果为了能处理这类峰值访问来投入资源随时待命,这样无疑时巨大的资源浪费。使用消息队列能够使用关键组件顶住突发的访问压力,而不会因为突发的超负荷请求而完全系统崩溃。

1.3.5、异步通信

很多时候,用户不想也不需要立即处理消息,消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它,想向队列中放入多少消息就存放多少,然后在需要的时候再去处理它。

1.4、消息队列的两种模式

1.4.1、点对点模式(一对一,消费者主动拉去数据,消息收到后消息清除)

消息生产者生产消息发送到Queue中,然后消息消费者从Queue中取出并且消费消息,消息被消费后,Queue中不再有存储,因此消费者不可能消费到已经被消费的消息。Queue支持存在多个消费者,但是对一个消息而言,只会被一个消费者消费。
在这里插入图片描述
1.4.2、发布/订阅模式(一对多,消费者消费数据之后不会清除消息)

消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息,和点对点不同的是,发布到topic中的消息会被所有订阅者消费。
在这里插入图片描述
其中发布/订阅模式又分两种,一种是消费者主动拉取数据,一种是消费者主动推送数据,kafka是消费者主动拉取数据。

二、Kafka架构

在这里插入图片描述
上图中一个topic配置了3个partition。Partition1有两个offset:0和1。Partition2有4个offset。Partition3有1个offset。副本的id和副本所在的机器的id恰好相同。

如果一个topic的副本数为3,那么Kafka将在集群中为每个partition创建3个相同的副本。集群中的每个broker存储一个或多个partition。多个producer和consumer可同时生产和消费数据。

2.1、broker

Kafka 集群包含一个或多个服务器,服务器节点称为broker。

broker存储topic的数据。如果某topic有N个partition,集群有N个broker,那么每个broker存储该topic的一个partition。

如果某topic有N个partition,集群有(N+M)个broker,那么其中有N个broker存储该topic的一个partition,剩下的M个broker不存储该topic的partition数据。

如果某topic有N个partition,集群中broker数目少于N个,那么一个broker存储该topic的一个或多个partition。在实际生产环境中,尽量避免这种情况的发生,这种情况容易导致Kafka集群数据不均衡。

2.2、Topic

每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)

类似于数据库的表名

2.3、Partition

topic中的数据分割为一个或多个partition。每个topic至少有一个partition。每个partition中的数据使用多个segment文件存储。partition中的数据是有序的,不同partition间的数据丢失了数据的顺序。如果topic有多个partition,消费数据时就不能保证数据的顺序。在需要严格保证消息的消费顺序的场景下,需要将partition数目设为1。

2.4、Replication

数据被存放到topic的partition中,但是partition有可能会损坏,因此我们需要对分区的数据进行备份(备份多少取决于对数据的重视程度)。

将分区分为Leader(1)和Follower(N),Leader负责写入和读取数据,Follower只负责备份,保证了数据的一致性。
在这里插入图片描述
2.5、Producer

生产者即数据的发布者,该角色将消息发布到Kafka的topic中。broker接收到生产者发送的消息后,broker将该消息追加到当前用于追加数据的segment文件中。生产者发送的消息,存储到一个partition中,生产者也可以指定数据存储的partition。

2.6、Consumer

消费者可以从broker中读取数据。消费者可以消费多个topic中的数据。

2.7、Consumer Group

每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)。

2.8、Leader

每个partition有多个副本,其中有且仅有一个作为Leader,Leader是当前负责数据的读写的partition。

2.9、Follower

Follower跟随Leader,所有写请求都通过Leader路由,数据变更会广播给所有Follower,Follower与Leader保持数据同步。如果Leader失效,则从Follower中选举出一个新的Leader。当Follower与Leader挂掉、卡住或者同步太慢,leader会把这个follower从“in sync replicas”(ISR)列表中删除,重新创建一个Follower。

2.10、Offset 偏移量

可以唯一的标识一条消息,偏移量决定读取数据的位置,不会有线程安全的问题,消费者通过偏移量决定下次读取数据的位置。消息被消费之后,并不被马上删除,这样多个业务就可以重复使用Kafka的消息。我们某一个业务可以通过修改偏移量达到重新读取消息的目的,偏移量由用户控制。消息最终还是会被删除的,默认的生命周期为1周(7*24小时)。

2.11、Zookeeper

Kafka 通过 zookeeper 来存储集群的 meta 信息。
在这里插入图片描述
Kafka拓扑结构图
在这里插入图片描述

三、Kafka的基本命令

启动Kafkaf服务
-daemon 是以后台方式启动kafka
bin/kafka-server-start.sh -daemon config/server.properties

kefka提供了多个命令用于查看、创建、修改、删除topic信息,也可以通过命令测试如何生产消息、消费消息等,这些命令位于kafka安装目录的bin目录下,下面列举kafka的一些常用命令的使用方法。

(1)显示topic列表

[root@zk-kafka002 kafka]# bin/kafka-topics.sh --zookeeper xxx.xxx.xxx.xxx:2182 --list

(2)创建一个topic,并指定topic属性(副本数、分区数等)

创建一个名称为 mytopic 的topic主题,3个分区,1个副本
[root@zk-kafka002 kafka]# bin/kafka-topics.sh --create --zookeeper xxx.xxx.xxx.xxx:2181,xxx.xxx.xxx.xxx:2181 --replication-factor 1 --partitions 3 --topic mytopic

(3)查看某个topic的状态

[root@zk-kafka002 kafka]# bin/kafka-topics.sh --describe --zookeeper xxx.xxx.xxx.xxx:2181 --topic mytopic
在这里插入图片描述
(4)删除topic

[root@zk-kafka002 kafka]# bin/kafka-topics.sh --zookeeper xxx.xxx.xxx.xxx:2182 --delete-topic mytopic

(5)生产消息

–broker-list 就是kafka的节点信息
[root@zk-kafka002 kafka]# bin/kafka-console-.sh --broker-list xxx.xxx.xxx.xxx:9092,xxx.xxx.xxx.xxx:9092 --topic mytopic

(6)消费消息,从头开始接受

[root@zk-kafka002 kafka]# bin/kafka-console-consumer.sh --zokeeper xxx.xxx.xxx.xxx:2181 --topic mytopic --from-beiginning

四、Kafka的工作流程在这里插入图片描述

Kafka中的消息是以topic进行分类的,生产者生产消息,消费者消费消息,都是面向topic的。

topic是逻辑上的概念,partition是物理上的概念,每个partition对应一个物理概念,每个partition对应一个log文件,该log文件存储的就是producer生产的数据。producer生产的数据会被不断地追加到该log文件末端,且每条数据都有自己的offset,消费组中的每个消费者,都会实时记录自己消费到那个offset,一遍出错恢复时,从上次的位置继续消费。

五、Kafka文件存储机制

在这里插入图片描述
由于生产者生产消息会不断追加到log文件末尾,为防止log文件过大导致数据数据定位效率低下,Kafka采用分片索引的机制,将每个partition分为多个segment,每个segment对应.log文件和.index文件,这些文件位于同一个文件夹下,该文件夹的命名规则为:topic名称+分区序号,例如:first这个topic有3个分区,则其对应的文件夹为first-0,first-1,first-2。
在这里插入图片描述
index和log文件以当前segment的第一条消息的offset命名,下图为index文件和log文件的结构示意图。
在这里插入图片描述
.index 文件存储大量的索引信息,.log文件存储了大量的数据,索引文件中的元数据指向对应数据文件中message的物理偏移量。

6、Kafka生产者分区策略

6.1、分区的原因

1、方便在集群中扩展,每个partition可以通过调整以适应所在的机器,而一个topic又可以有多个partition组成,因此整个集群就可以适应任意大小的数据。

2、可以提高并发,因为可以以partition为单位进行读写。

6.2、分区的原则

我们需要将生产者发送的数据封装成一个ProducerRecord对象,下图是生成ProducerRecord对象的一些api。
在这里插入图片描述
1、指明partition的情况下,直接将指明的值作为partition的值(Integer partition 就是分区的id)。

2、没有指明partition值的情况下,将key的hash值与topic下partition的总数进行取余计算,从而得到
partition值。

3、既没有partition值,也么有key值的情况下,第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与topic中可用的partition总数取余计算,从而得到partition值,也就是常说的 round-robin 算法(轮询算法)。

7、Kafka数据可靠性保证

为了保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到producer发送的数据后,多需要向producer发送ack(ackonwledgement 确认收到),如果producer收到ack,就会进行下一轮发送,否则重新发送数据。在这里插入图片描述
副本数据同步策略分析:
在这里插入图片描述
7.1、kafka选择了方案2,原因如下:

1、同样为了容忍n台服务器节点故障,第一种方案需要2n+1个副本,而第二种方案需要n+1个副本,而Kafka每个分区都有大量的数据,第一种方案会造成大量数据的浪费。

2、虽然第二种方案的网络延迟较高,但网络延迟对Kafka的影响较小。

7.2、ISR

采用方案二之后,假设以下场景:leader收到数据,所有的follower开始同步数据,但有一个follower,因为某种故障,迟迟不能与leader进行同步,那leader就要一直等待下去,直到它同步完成才能发ack,这个问题Kafka怎么解决?

Leader维护了一个动态的 in-sync replica set(ISR),就是和leader保持同步的follower集合,当ISR中的follower完成数据同步之后,leader就会给producer发送ack。如果follower长时间未leader同步数据,则该follower将被踢出ISR,该时间阀值由 replica.lag.time.max.ms 参数决定,leader发生故障之后,就会从ISR中选举新的leader。

7.3、ack应答机制

对于某些不是很重要的消息,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没有必要等到ISR中所有的follower全部同步成功再给producer返回ack。

因此,Kafka为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡,选择以下的acks参数配置情况:

0: producer 不等待broker的ack,这一操作提供了一个最低的延迟,broker一接受到消息,还未写入磁盘,就已经返回,当broker故障时有可能丢失数据。

1: producer 等待broker的ack,partition 的leader落盘成功后返回ack,如果在followed同步之前leader故障,那么将会丢失数据。

-1(all): producer 不等待broker的ack,partition 的leader和follower(ISR中的) 全部落盘成功之后才会返回ack。但是如果在follower同步完成之后,broker发送ack之前,leader发生故障,那么会造成生产者发送重复消息
在这里插入图片描述
7.4、故障处理细节

Log文件中的HW和LEO
在这里插入图片描述
LEO: 指的是每个副本最大的offset。
HW: 指的是消费者能见到的最大offset,ISR队列中最小的LEO。

1、follower故障

follower临时发生故障后会被踢出ISR,待该follower恢复后,follower会读取本地磁盘的记录上次的HW,并将log文件高于HW的部分截取,从HW开始向leader同步,等该follower的LEO大于等于该Partiton的HW,即follower追上leader之后,就可以重新加入ISR。

2、leader故障

leader发生故障之后,会从ISR中选一个新的leader,之后为了保证副本之间的数据一致性,其余的follower会先将各自的log文件高于HW的部分进行截取,然后从新的leader同步数据。

注意:这里只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。

7.4、Exactly once (精准一次性)语义

将服务器的ack级别设置为-1,可以保证producer到broker之间不会丢数据,即 At least once,相对的将服务器的ack级别设置为0,可以保证生产者每条消息只会被发送一次,即 At most once。

At least once 可以保证数据不丢失,但是不能保证数据不重复,相对的,At most once 可以保证数据不重复,但是不能保证数据不丢失。但是对于一些非常重要的数据,比如说交易数据,下游数据消费者要求数据既不能丢失,也不能重复,即 Exactly once 语义

在0.11版之前的Kafka,对此是无能为力的,只能保证数据不丢失,再在下游消费者对数据做全局的去重,对于多个下游消费者的情况,每个都需要做单独的去重工作,这样对性能造成很大的影响。

0.11版本的Kafka,引入了一个重大特性——幂等性,所谓的幂等性是指Producer无论向Server发送多少次重复的数据,Server都只会持久化一条,幂等性结合 At least once 语义就构成了Kafka的Exactly once 。

At least once + 幂等性 = Exactly once

要启用幂等性,只需要将Producer的参数中 enable.idempotence 设置为true即可 (此时ack就会默认设置为-1),Kafka的幂等性实现其实就是将原来下游需要做的去重放在了数据上游,开启幂等性的Producer在初始化的时候会被分配一个PID,发送同一个Partition的消息会附带Sequence Number,而broker端会对<PID,Partition,Sequence Number>做缓存,当具有相同的主键的消息提交时,broker只会持久化1条。

但是Producer重启PID会发生变化,同时不同的Partition也具有不同的主键,所以幂等性无法保证跨分区或跨会议的Exactly once

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值