一、概述
1.定义
1)传统定义:分布式的消息队列,是发布/订阅形式的
2)最新定义:流平台(海量数据的存储和计算)
2.消息队列的应用场景
1)缓存消峰(针对于海量数据一时间处理不聊放入队列中持续的处理)
2)解耦(可以使用各种数据来源进行统一处理)
3)异步通信(将非核心有延迟的业务放入消息队列中处理)
3.发布订阅模式特点
1)可以有多个生产者和多个消费者且相互独立
2)可以有多个topic,在消费者消费完数据后不会删除数据
4.架构
1)生产者:
2)broker:服务器集群, broker中可以有不同的topic(主题)来对数据进行分类
分区进行对大量数据的分块存储, 创建副本去保证数据的安全和可靠,副本分为leader和follower,
生产者和消费只对leader进行处理操作
3)消费者:消费者之间是相互独立的,一个分区只能由一个消费者来处理,保证数据不被重复处理
4)zookeeper:存储broker.ids,存储副本的leader和follower信息
二、入门
1.安装
1)broker,id必须全局唯一代表是服务器的标识
2)log.dirs配置存储目录。 zk/kafka 配置zookeeper存储kafka的位置
3)先停止kafka才能停止zookeeper
2.常用命令
1)主题 kafka-topic.sh 参数:–bootStrap-server --topic --create --list --describe --replication-factor --partitions
2)生产者 kafka-console-producer.sh 参数 --bootStrap-server --topic
3)消费者 kafka-console-consumer.sh 参数 --bootStrap-server --topic
三、生产者
-
原理:通过拦截器,序列器,分区器进行处理数据,放入缓冲队列(32m)中一批次发送16k,缓存队列是内存池实现的,通过发送进程发送到broker进行落盘持久化。发送进程会进行一些应答重试操作保证数据发送的可靠性,ack应答为0是不需要应答持续进行发送,数据安全性不高效率较高,ack应答为1,leader进行落盘持久化后才会继续发送数据,但如果leader宕机follower没有及时备份的时候会出现数据不一致的问题,ack应答为-1(all),leader和follower都完成数据的持久化后才会继续发送数据。应答失败时会进行数据重新发送。
-
异步发送Api
0)属性配置(properties对象)
选择提供的静态常量变量进行配置对象属性的赋值,参数 :bootstrap-server key value 序列化器
1)通过构造方法创建生产者对象
KafkaProducer<String,String>()
2)发送数据,调用send()方法,send方法提供了多种重载形式,可以有不同的参数实现对于功能,提供了发送成功的回调函数
3)关闭资源
-
生产者进行同步发送,send().get()
-
集群存储分区
1)好处 更有利于存储和计算,同时提高了生产者和消费者进行处理的并行度
2)默认分区规则:发送时指定分区; 或对发送key的hash值对分区数进行取余 ;没有指定key和分区的时候使用粘性分配的规则Kafka采用Sticky Partition(黏性分区器),会随机选择一个分区,并尽可能一直使用该分区,待该分区的batch已满或者已完成,Kafka再随机一个分区进行使用(和上一次的分区不同)
3)自定义分区器重写partitioner接口,定义自己分区规则
-
吞吐量的提高
1)批次大小的设置 16k 32k
2)linger.ms 默认0 设置为5ms到100ms
3)设置压缩机制
4)缓存队列大小 32m -> 64m
-
可靠性
ack应答机制来控制可靠性,-1时 副本数大于等于2且isr>= 2时是完全可靠,但是会出现数据重复问题
幂等性:通过<pid,分区号,序列化(自增)>来判断是否为同一个数据,解决数据重复问题
事务:底层基于幂等性 参数流程: 初始化 、 启动 、消费者offset 、提交 、终止
四、broker
1.副本
1)好处,设置副本来提高可靠性做数据的备份
2)生成环境通常配置2个副本,默认为1个
3)副本有leader和follower之分,生产者和消费者操作的只是leader,follower只是在做备份
4)isr维护一个副本列表,保证leader和follower之间能够正常通讯,采用类似心跳机制,follower30s无应答时会将其踢出列表,之后的备份通讯就不对其展开。
5)副本选举机制,Controller复制副本之间的选举机制,根据isr和ar进行列表选择新的leader
6)leader宕机:follower上位之后需要保证数据一致性问题,通过leo和hw(记录数据备份的位置)以新上位的leader为主所有follower截取掉比leader多的部分,重新开始获取数据
7)follower宕机:follower宕机后会被踢出isr列表,其余主机继续正常工作,恢复之后会根据上次的hw值截取掉多余的部分(因为认定这部分是未经确认的数据),然后继续向leader进行同步,当leo大于当前分区的hw时则会重新加入isr
8)副本在集群中的默认分配规则,通过错位的形式尽可能将数据均匀的分配在集群服务器上,达到负载均衡和数据可靠的效果
9)副本的手动分配规则:制定分配计划,执行分配计划,验证分配计划
10)副本leader的负载均衡计划
11)手动为分区增加副本因子
2.存储机制: broker topic partition log segment(1g) lg 稀疏索引 每4kb数据存储一条索引
3.文件删除机制:默认文件保存7天,根据业务场景进行时间的调整
策略: 删除需要文件中的所有数据都过期才进行删除,压缩将相同key的value值只保存一个进行覆盖处理
4.高效读写
1)使用集群部署,采用分区策略提高了生成和消费的并行度
2)选择稀疏索引来提高效率
3)顺序读写来提供读写速度
4)零拷贝:kafka的数据加工处理操作交由Kafka生产者和Kafka消费者处理。Kafka Broker应用层不关心存储的数据,所以就不用走应用层,传输效率高。
页缓存:Kafka重度依赖底层操作系统提供的PageCache功 能。当上层有写操作时,操作系统只是将数据写入PageCache。当读操作发生时,先从PageCache中查找,如果找不到,再去磁盘中读取。实际上PageCache是把尽可能多的空闲内存都当做了磁盘缓存来使用。
五、消费者
1.消费流程
2.消费者组
3.实现消费
1)配置信息: 连接 反序列化器 组id
2)创建消费者对象
3)订阅主题
4)消费数据
4.按照分区消费
5.分区分配策略以及再平衡:
1)range(默认):通过 partitions数/consumer数 来决定每个消费者应该消费几个分区。如果除不尽,那么前面几个消费者将会多消费 1 个分区。range再平衡会将宕机的消费者统一分配一个消费者,当45s以后会再次进行range分配。
2)roundrobin(轮询算法): RoundRobin 轮询分区策略,是把所有的 partition 和所有的consumer 都列出来,然后按照 hashcode 进行排序,最后通过轮询算法来分配 partition 给到各个消费者。roundrobin再平衡会将宕机的消费者任务进行轮询分配给其余消费者,45s以后会将所有任务统一进行roundrobin分配。
3)粘性:首先会尽量均衡的放置分区到消费者上面,在出现同一消费者组内消费者出现问题的时候,会尽量保持原有分配的分区不变化。
6.offset
1)默认存储在系统主题中,在0.9版本之前存储在zookeeper中,会增加大量的网络通讯压力。所以之后存储在系统主题中
2)自动提交 5s 默认
3)手动提交 提供了同步和异步的方法
4)指定offset进行消费
5)按照指定时间消费
6)自动提交会导致重复消费问题,在下一次offset还未提交之间broker宕机,新的消费者就会读取之前的offset导致重复消费
7)手动提交会导致漏消费问题,当offset被提交时,数据还在内存中未落盘,此时刚好消费者线 程被kill掉,那么offset已经提交,但是数据未处理,导致这部分内存中的数据丢失。
8)事务:如果想完成Consumer端的精准一次性消费,那么需要Kafka消费端将消费过程和提交offset过程做原子绑定。此时我们需要将Kafka的offset保存到支持事务的自定义介质。
9)数据积压:kafka消费能力不足 , 下游数据处理不及时
六、生产调优
1.假设100万日活 * 每人每天产生日志100条 = 1亿条日志(中型公司)
处理日志速度: 1亿条/(24 * 3600) = 1150条/s
一条日志平均为1k,1150 * 1k = 1m/s 峰值: 1m/s * 20 = 20m/s
2.服务器台数: 2 * (生产者峰值生产速率 * 副本数 / 100) + 1 = 3台
3.磁盘选择: kafka 按照顺序进行读写,则机械硬盘和固态硬盘的读写速度基本一致,采用机械硬盘
1亿条 * 1k = 100G 100G * 7 = 700G 留30%的空间 1T
4.内存 5. CPU线程 6.带宽
七、生产者
八、broker
九、消费者
十、相关面试题目:
-
Apcahe kafka是什么 ?
Apache kafka是一款分布式流处理框架,用于构建实时流处理应用。它有一个核心的功能即作为企业级的消息引擎被广泛使用。它具有高吞吐,可持久化,可水平扩展,支持流数据处理等多种特性 -
kafka有什么用?
消息系统:kafka和传统的消息中间件都具备系统解耦、冗余存储、流量消峰、缓冲、异步通信、扩展性、可恢复性等功能。于此同时,kafka还提供了大多数消息系统难以实现的消息顺序性保证及回溯性消费的功能。
存储系统:kafka可以将消息持久化到磁盘上去,相比于其他基于内存存储的系统而言有效的降低了消息丢失的风险。这得益于其消息持久化和多副本机制。 -
什么是消费者组?
1)定义:是kafka提供的可扩展且具有容错性的消费者机制。
2)原理:消费者组是有一个或多个组id相同消费者实例组成的,他们负责共同订阅若干个主题分区。每个分区只能被同一消费组内一个消费者消费。策略有Range(默认),轮询,粘性。消费者组会采用以上策略来对消费任务进行划分,以及在某个消费者实例挂掉后的再平衡。 -
在kafka中,zookeeper的作用是什么?
目前kafka使用zookeeper来存放集群元数据、成员管理、Controller选举以及其他的管理类任务。存放元数据是指主题分区的所有数据都保存在zookeeper中,且以它保存的数据为权威。“成员管理”是指broker节点在集群中的注册、注销以及属性变更等,Controller选举是指集群中的Controller选举其中的一个作为leader,其他管理类任务包括主题删除,参数配置等等。因为kafka的发展前景和势头也比较大,所以在kafka2.8之后可以选择不依赖于zookeeper,kafka提供Kraft模式来抛弃zookeeper,在未来kafka可能将会完全不再使用zookeeper进行配合。
-
简述下kafka中副本的leader和follower的区别?
kafka的副本当前分为领导者和追随者,只有领导者才能对外提供读写服务响应clients的请求。follower采用pull的方式被动地去同步leader副本中的数据,并在leader宕机之后顶替成为新的leader。 -
既然kafka中有副本形式,那么为什么不采用读写分离的模式?
首先在kafka2.4版本之后通过引用了新的broker端参数,允许了副本有限度的提高读服务。读写分离使用于那种读负载很大,而写操作相对不频繁的场景,可kafka不属于这样的场景,同时kafka采用poll的方式来实现follower的同步,因此follower和leader之间存在不一致窗口,就会出现消息滞后消息不一致的问题。而同时kafka集群会均匀的将leader副本分配在broker节点来保证各个节点读写压力的平衡。 -
监控kafka的框架?
Kafka-Eagle -
如何调优kafka?
Producer 端:增加 batch.size、linger.ms,启用压缩,关闭重试等。Broker 端:增加 num.replica.fetchers,提升 Follower 同步 TPS,避免 Broker Full GC 等。
Consumer:增加 fetch.min.bytes 等
-
LEO、HW代表什么含义有什么作用?
LEO(Log Een Offset):每个副本的最后一个offset,即最新的offset+1
HW(High Watermark):所有副本中最小的LEO
1)leader故障时:leader发生故障时会从Isr中选出一个新的leader,为保证多个副本之间的数据一致性问题,其余的follower会先将各自的log文件中高于HW的部分截掉,因为它认为这些是没有安全保障的数据,然后从新的leader中开始同步数据。这样只能保证数据的一致性却存在数据的丢失和重复的问题。2)follower故障时:follower会被临时踢出Isr,该follower恢复后,follower会读取本地磁盘记录的上次的HW,将log文件中高于HW的部分截掉从HW处开始同步的leader的数据。等该follower的LEO大于等于该分区的HW时即可重新加入Isr。
-
ISR、AR代表什么含义?
ISR(In-Sync Replicas):与leader副本保持一定程度同步的副本(包括Leader) OSR(Out-Sync Relipcas):与leader滞后过多副本(不包括leader)ps:参数配置滞后范围 leader发生故障时会从AR中选出一个新的leader,如果此leader在ISR中则顶替成为新的leader
AR(Assigned Repllicas):分区中所有副本统称 -
发送消息的分区策略有哪些?
1)轮询:依次将消息发送该topic下的所有分区,如果在创建消息的时候 key 为 null,Kafka 默认采用这种策略。
2)key 指定分区:在创建消息是 key 不为空,并且使用默认分区器,Kafka 会将 key 进行 hash,然后根据hash值映射到指定的分区上。这样的好处是 key 相同的消息会在一个分区下,Kafka 并不能保证全局有序,但是在每个分区下的消息是有序的,按照顺序存储,按照顺序消费。在保证同一个 key 的消息是有序的,这样基本能满足消息的顺序性的需求。但是如果 partation 数量发生变化,那就很难保证 key 与分区之间的映射关系了
3)自定义策略:实现 Partitioner 接口就能自定义分区策略。
4)指定 Partiton 发送
12.acks代表什么含义有什么用?
1)acks = 1,默认为1。生产者发送消息,只要 leader 副本成功写入消息,就代表成功。这种方案的问题在于,当返回成功后,如果 leader 副本和 follower 副本还没有来得及同步,leader 就崩溃了,那么在选举后新的 leader 就没有这条消息,也就丢失了。
2)acks = 0。生产者发送消息后直接算写入成功,不需要等待响应。这个方案的问题很明显,只要服务端写消息时出现任何问题,都会导致消息丢失。
3)acks = -1 或 acks = all。生产者发送消息后,需要等待 ISR 中的所有副本都成功写入消息后才能收到服务端的响应。毫无疑问这种方案的可靠性是最高的,但是如果 ISR 中只有leader 副本,那么就和 acks = 1 毫无差别了。
-
kafka为什么这么快?
1)kafka采用了顺序读写磁盘,基于磁盘的随机读写的话会很慢,顺序读写磁盘会极大的提高性能。
2)kafka采用了分主题分区的形式,这样提高了生产者和消费者的并行度,提高了数据读取的效率
3)kafka读数据采用了稀疏索引的形式可以快速的定位要消费数据的位置
4)页缓存:kafka重度依赖底层操作系统提供的页缓存功能,当上层有写操作的时候,操作系统只是将数据写入PageCache。当读操作发生时先从PageCache中查找,如果找不到再去磁盘中读取,实际上PageCache就是把尽可能多的空闲内存当成了磁盘的缓存来使用,我们一般预留25%的空间作为页缓存空间。
5)零拷贝:kafka的数据加工处理完全交给kafka的生产者和消费者来处理,在kafka的Broker应用层不关心存储的数据,所以不需要走应用层,传输效率更高省去了一步拷贝的步骤。
14.kafka为什么会出现漏消费和重复消费的问题?
1)先提交offset,再消费消息:offset被提交到kafka broker,但是消息还没来得及被消费,消费者故障了需要重启,由于offset已经被提交了,所以这个情况会发生漏消费的问题。
2)先消费消息,再提交offset,先把消息消费完了,但offset还未被提交,消费者故障重启,消息已经被消费,但offset未提交,此时故障会产生消息重复消费的问题。