简介:
消息队列用于存放消息的组件
程序员可以将消息放入到队列中,也可以从消息队列中获取消息
很多时候消息队列不是一个永久性的存储,是作为临时存储存在的(设定一个期限:设置消息中MQ中保存10天)
消息队列中间件:消息队列的组件,例如:Kafka,ActiveMQ,RabbitMQ,rocketMQ,ZeroMQ
应用场景:
应用解耦、数据管道、消息系统、流处理、日志收集与分发
好处:
异步处理
可以将一些比较耗时的操作放在其他系统中,通过消息队列将需要处理的消息进行存储,其他系统可以消费消息队列中的数据
系统解偶
原先一个微服务生死勇敢接口http调用另一个微服务,这时候耦合很严重,只要接口发生变化就会导致系统不可用
使用消息队列呀将系统进行解偶,现在第一个微服务可以将消息放入到消息队列中,另一个微服务可以从消息队列中把消息取出来进行处理,进行系统解偶
流量削峰
因为消息队列是低延迟,高可靠,高吞吐的(Kafka吞吐量10W),可以应对大量并发
日志处理
可以使用消息队列作为临时存储,或者一种通信管道
mysql吞吐量8000,kafka响应快低延迟,mysql延迟比kafka高,先放到kafka中让用户等待
消息队列的两种模型
生产者和消费者模型
生产者负责将消息生产到MQ中
消费者负责从MQ中获取消息
生产者和消费者是解偶的,可能是生产者一个程序、消费者是另外一个程序
消息队列的两种模式:
点对点模式 :一个消费者消费一个消息
特点:
每个消息只有一个接收者(即一旦被消费,消息就不再消息队列中)
发送者和接收者间没有依赖性,发送者发送消息之后,不关有没有接收者在运行,都不影响到发送者下次发送消息
接收者在成功接收消息之后需向队列应答成功,以便消息队列删除当前接收的消息
发布订阅模式: 多个消费者可以消费一个消息
特点:
每个消息可以多个订阅者
发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,
Kafaka是一个分布式的流平台
特点:发布和订阅流数据流,类似于消息队列或者是企业消息传递系统
以容错的持久化方式存储数据流
处理数据流
Kafka集群搭建
Kafka3.0之前依赖Zookeeper的
注意:每一个kafka的节点都需要修改broker.id(每个节点的标识,不能重复)
log.dir数据存储目录需要配置
Kafka的生产者/消费者/工具
安装kafka集群,可以测试以下
创建一个topic主题(消息都是存放在topic中,类似mysql建表的过程)
基于kafka的内置测试生产者脚本来读取标准输入(键盘输入)的数据,并放入到topic中
基于kafka的内置测试消费者脚本来消费topic中的数据
推荐大家开发的使用 kafka tool
浏览kafka集群节点,多个topic,多个分区
创建topic/删除topic
浏览zookeeper中的数据
kafka介绍
Producer:发布消息的对象称之为主题生产者(kafka topic producer)
Partition:分区,每个主题可以创建多个分区,每个分区都由一系列有序和不可变的消息组成
Topic:kafka将消息分门别类,每一类的消息称之为一个主题(Topic)
Consumer:订阅消息并处理发布的消息的对象称之为主题消费者(consumers)
Broker:已发布的消息保存中一组服务器中,称之为kafka集群。集群中的每一个服务器都是一个代理(broker)。消费者可以订阅一个或多个主题(topic),并从Broker拉数据,从而消费这些已发布的消息
Record:消息,消息队列基础通信单位
Replica:副本,每个分区都由一个至多个副本存在,它的主要作用是存储保存数据,以日志对象的形式体现。副本又分为leader副本和follower副本
Offset:偏移量,每一个消息在日志文件中的位置都对应一个按序递增的偏移量,你可以理解为类似数组的存储形式
kafka2.0和3.0
kafka2.0:一个集群所有节点都是broker角色,利用zookeeper的选举能力从多个broker中选举处理一个controller控制器,同时控制器将集群元数据信息(比如主题分类、消费进度等)保存到zookeeper,用于集群个节点之间分布式交互
kafka3.0:假设一个集群有四个broker,配置指定其中三个作为controller角色。使用Kraft机制实现controller主控制器的选举,从三个controller中选举出来一个Controller作为主控制器,其他的两个备用。zookeeper不再被需要。相关的集群元数据信息以kafka日志的形式存在(即:以消息队列消息的形式存在)
Kafka的基准测试工具
kafka单机基准测试,单机搭建及介绍_kafka 单机-CSDN博客
Kafka中提供了内置的性能测试工具
生产者:测试生成美妙传输的数据量(多少条数据、多少m的数据)
消费者:测试消费每条拉取的数据量
对比生产者和消费者:消费者的速度更快
生产者程序开发
1.创建链接
bootstrap.servers:kafka的服务器地址
Acks:表示当生产者数据到kafka中kafka中会以什么样的策略返回
key.serializer:kafka中的消息是以可以,value键值对存储的,而是生产者生产的消息是需要在网络上传到的,这里指定的事StringSerializer方式,就是以字符串方式发送(将来还可以使用其他的一些序列化框架:GoogleProtoBuf、Avro)
value.serializer:同上
2.创建一个生产者对象KafkaProducer
3.调用send方法发送消息(ProducerRecor,封装是key-value键值对)
4.调用Future.get表示带服务端的相应
5.关闭生产者
消费者程序开发
group.id:消费者组的概念,可以在一个消费组中包含多个消费者。如果若干个消费者的group.id是一样的,表示它们就在一个组中,一个组中的消费者是共同消费kafka中topic的数据
Kafka是一种拉消息模式的消息队列,中消费者中会有一个offset,表示从哪条消息开始拉取数据
kafka Consumer.poll:Kafka的消费者API是一批一批数据的拉取
生产者使用一步方式生产消息
使用匿名内部类实现CallBack接口,该接口中表示kafka服务响应给客户端,会自动调用onCompletion方法
Metadata:消息的元数据(属于哪个topic、属于哪个partition、对应的offset是什么)
Exception:这个对象kafka生产消息封装了出现的异常,如果为null,表示发送成功,如果不为null,表示出现异常
Kafka中的重要概念
broker
Kafka服务器进程,生产者、消费者都要连接broker
一个集群由多个broker组成,功能实现kafka集群的负载均衡、容错
producer:生产者
consumer:消费者
topic:主题,一个kafka集群中,可以包含多个topic。一个topic可以包含多个分区是一个逻辑结构,生产、消费消息都需要指定topic
Partition:kafka集群的分布式就是由分区来实现的。一个topic中的消息可以分布在topic中不同partition中
Repica:副本,实现kafka集群的容错,收拾下partition的容错。一个topic至少应该包含大于一个的副本
Consumer group:消费者组,一个消费者组中的消费者可以共同消费topic中的分区数据。每一个消费组都一个唯一的名字。配置group.id一样的消费者生死属于同一个组的
Offset:偏移量。相对消费者、partition来说,可以通过offset来拉取数据
消费者组
一个消费者组中可以包含多个消费者,共同来消费topic中的数据
一个topic中如果只有一个分区,那么这个分区只能呗某个组中的一个消费者消费
有多少个分区,那么就可以被同一个组内的多少个消费者消费
Comsumer group是kafka提供的可扩展且具有容错性的消费者机制
一个消费者组可以包含多个消费者
一个消费者组有一个唯一的ID(group id)
组内的消费者一起消费主体的所有分区数据
分区(partition)
在kafka集群中,主题 被分为多个分区
副本(Replicas)
副本可以确保某个服务器出现故障时,确保数据依然可用
Kafka中,一般都会设计副本的个数>1
主题(topic)
主题是一个逻辑概念,用于生产者发布数据,消费者拉取数据
Kafka中的主题必须要有标识符,二期是唯一的,kafka中可以有任意数量的主题,没有数量上的限制
在主题中的消息是有结构的,一般一个主题包含某一类消息
一旦生产者发送消息到主题中,这些消息就不背更新(更改)
偏移量(offset)
Offset记录者下一条江要发送给consumer的消息的序号
默认kafka江offset存储在zookeeper中
在一个分区中,消息是有顺序的方式存储着,每个在分区的消费都是有一个递增的id,这个就是偏移量的offset
偏移量在分区中才是有意义的。在分区之间,offset是没有任何意义的
Kafka生产者幂等性
Kafka中生产者生产消息到partition,如果直接发送消息,Kafka会将消息保存到分区中,单kafka会返回一个ack给生产者,表示当前操作是否成功,是否已经保存了这条消息,如果ack响应的过程失败了,此时生产者会重试,继续发送没有发送成功的消息,kafka优惠保存一条一摸一样的消息
在kafka中可以开启幂等性
当kafka的生产者生产消息时,会增加一个pid(生产者的唯一编号)和sequence number(针对消息的一个递增序列)
发送消息,会连着pid和sequence number 一并保存下来
如果ack响应失败,生产者重试,再次发送消息时,kafka会根据pid,sequence number是否需要在保存一条消息
判断条件:生产者发送过来的色quence number 是否小于等于partition中消息对应的sequence
Kafka中的分区副本机制
生产者写入分区策略
一个topic有多个分区
轮训策略:(按照消息尽量保证每个分区的负载)策略,消息会均匀的分布到每个oartition
写入消息的时候,可以为null的时候好,默认使用的是轮训策略
随机策略(不使用)
按key分配策略,可以.hash()%分区的数量
自定义分区策略(类似于MapReduce指定分区)
乱序问题
在Kafka中生产者是有写入策略,如果topic有多个分区,就会将数据分散在不同的partition中存储
当partition数量大于1的时候,数据(消息)会打散在不同的partition中
如果只有一个的分区,消息是有序的
Kafka中的消息是全局乱序的,局部partition是有序的
如果外卖要实现消息总说有序的,可以将连续的消息放到一个partition,但kafka就失去了分布式的意义
消费者组Consumer Group Rebalance机制
再均衡:
在某些情况下,消费者组中的消费者消费的分区会产生变化,会导致消费者分配不均匀(例如:有两个消费者消费3个,因为某个partition崩溃了,还有一个消费者当前没有分区要削峰),kafka Consumer Group就会启用rebalance机制,重新平衡这个Consumer Group内的消费者消费的分区分配
触发机制
消费者数量发送变化:
1.某个消费者crash
2.新增消费者
Topic的数量发送变化
1.某个topic被删除
partition的数量发送变化
1.删除partition
2.新增partition
不良影响
发送rebalance,所有的consumer将不再工作,共同来参与再均衡,直到每个消费者都已经被成功分配所需要消费的分区为止(rebakance结束)
消费者的分区分配策略
分区分配策略:保障每个消费者尽量能够均衡的消费分区的数据,不能出现某些消费者消费分区的数量特别多,某个消费者消费的分区特别少
Range分配策略(返回分配策略):kafka默认的分配策略
n:分区的数量/消费者数量
m:分区的数量%消费者数量
前m个消费者消费n+1个分区
剩余的消费者n个分区
RoundRobin分配策略(轮询分配策略)
消费者挨个分配消费的分区
Skriky粘性分配策略
在没有发送rebalance跟轮询分配策略是一致的
在发生了rebalance,轮询分配测试,重新走一遍轮询分配的过程。二粘性会保证跟上一次的尽量一致,至少将新的需要分配的分区,均匀的分配到现有可用的消费者中即可
减少上下文的切换
副本的ACK机制
Producer是不断的往kafka中写入数据,写入数据会有一个返回结果,表示是否写入成功。这里对应有一个ACKs的配置
acks=0:生产者只管写入,不管是否写入成功,可能会数据丢失。性能是最好的
acks=1:生产者会等到leader分区写入成功后,返回成功,接着发送下一条
acks=-1/all:确保消息写入到leader分区、还确保消息写入到对应副本都成功后,接着发送下一条,性能是最差的
根据业务情况来选择ack机制,是要求性能最高,一部分火速数据丢失影响不大,可以选择0/1。如果要求数据一定不能丢失,就给配置为-1/all。
分区中是有leader和follower的概念,为了确保消费或者消费的数据寒山寺一致的,只能从分区leader去读写消息,follewer做的事情就是同步数据,Backup。
高级API(High-Level API)、低级API(Low-level API)
高级API就是直接让Kafka帮助管理、处理分配、数据
offset存储中ZK中
有kafka的rebalance来控制消费者分配的分区
开发起来比较简单,无需开发者关注底层细节
无法做到细颗粒度的控制
低级API:又便携的程序自己控制逻辑
自己来管理offset,可以将offset存储中ZK、mysql、Redis、HBase、Flink的状态存储
指定消费者拉取某个分区的是苏剧
可以做到细颗粒度的控制
原有的Kafka的策略会失效,需要我们自己来实现消费机制
Kafka的可视化工具kafka-eagle
kafka原理
leader和follower
leader与follower相对分区有意义,不是相对broker
Kafka在创建topic的时候好,会尽量分配分区在不同的broker中,其实就是负载均衡
Leader职责:读写数据
Follower职责:同步数据、参与选举(leader crash之后,会选举一个follower重新称为分区leader
注意和zookeeper区分
zk的leader负责读、写,follower可以读取
Kafka的leader负责读写、follower不能读写数据(确保每个消费者的数据是一致的),kafka一个topic有多个分区leader,一样可以实现数据操作的负载均衡
AR/ISR/OSR
AR指的是一个topic分区的全部副本
ISR指的是正在同步的副本(当前有几个follower存活的)
OSR指的是不再同步的副本
AR=ISR+OSR
leader选举
Controller:controller是kafka集群的老大,是针对Broker的一个角色
Controller是2高可用的,是用过zzk来进行选举
Leader:是针对partition的一个角色
Leader是通过ISR来进行快速选举
如果kafka是基于ZK来进行选举,ZK的压力可能会比较大。例如:某个节点崩溃,这个节点上不仅仅只有一个leader,是有不少的leader需要选举。通过ISR快速进行选举
leader的负载均衡
如果某个broker crash之后,就可能会导致partition的leader分布不均匀,就是一个broker上存在一个topic下不停partition的leader
通过一下指令,可以将leader分配到有限的leader对应的broker,确保leader是均匀的
重启指定节点下的分区命令:
bin/kafka-leader-election.sh —bootstrap-server node1.itcast.cn:9092 —topic test —partition=2 —election-type preferred
node1.itcast.cn:9092kafka节点名称和端口号
partition=2:数字2是重启的那个leader
Kafka的读写流程
写流程:通过zookeeper找到partition对应的leader,leader是负责读写的
producer开始找写入数据
ISR里面的foolower开始同步数据,并返回给leader ACK
返回给producerACK
读流程:通过zookeeper找partition对应的leader,leader是负责读的
通过zookeeper找到消费者对应的offset
然后开始offset往后顺序拉取数据
提交offfset(自动提交—每个多少秒体检一次offset、手动提交—放入到事物中提交)
Kafka的物理存储
稠密索引和稀疏索引
因为消费者对应的offset是针对整个分区的,而消息是存储在具体某一个segment段中,所以需要通过这个offset,找到在当前这个segment中的offset
Kafka的数据组织结构
Topic->partition->segment->.log数据文件、.inexd(稀疏索引)、.timeindex(根据时间做的索引)
深入了解读数据的流程
消费者者的offset是一个针对partition全局offset
可以根据这个offset找到segment段
接着需要将全局的offset转换成segment的局部offset
根据局部的offset,就可以从(.index稀疏索引)找到对应的数据位置
开始顺序读取
消息传递的语义性
Finl里面有对应的每种不同机制的保障,提供Exactly-Once保障(二阶段事物提交方式)
At-most once:最多一次(直接把 数据消费到,不管有没有成功,可能会有数据丢失)
At-least once:最少一次(有可能会出现重复消费)
Exactly-Once:仅有一次(事物性的保障,保证消息有且仅被处理一次)
Kafka的消息不丢失
Broker消息不丢失:因为有副本relicas的存在,会不断的从leader中通不副本,所以,一个broker crash,不会导致数据丢失,除非是只有一个副本
生产者消息不丢失:ACK机制(配置成ALL/-1)、配置0或者1可能会存在丢失
消费者消费不丢失:重点控制offset
At-least once:一种数据可能会重复消费
Exactly-Once:仅有一次
Kafka数据积压
数据积压值得是消费者因为有一些外部的IO、一些比较耗时的的操作(Full GC—Stop the world),就会造成消息在partition中一直存在得不到消费,就会产生是数据积压
在企业中,我们要有监控系统,如果出现这种情况,需要尽快处理。虽然后续的Spark Streaming/Flink可以实现背压机制,电脑上数据累积太多一定对实时性是有说影响的
数据积压的情况:
MySQL错误、网络延迟
Kafka中数据清理
两种清理方式:
日志清理(Log Deletion):按照指令的策略直接删除不符合条件的日志
日志压缩(Log Compaction):按照消息的key进行整合,有相同key的但有不同value值,只保留最后一个版本
日志删除
日志删除是以(segment日志)为单位来进行定期清理的
定时日记删除任务
定期检测和删除不符合保留提哦啊就的日记分段文件,周期默认是300000(五分钟),可以通过broker端参数log.retention.check.interval.ms来配置。
日志分段保留策略三种:
1.基于实际的保留策略
log.retention.hours
log.retention.minutes
log.retention.ms
2.基于日志大小的保留策略
3.基于日志起始偏移量的保留策略
删除日志分段时,将删除日志分段文件添加上“.deleted“的后缀,Kafka后台定时任务回定期删除这些文件,任务的延迟执行时间可以通过file.delete.delay.ms参数来设置,默认值为60000(一分钟)