消息队列之—kafka

消息队列是啥

消息队列英文叫Message Queue。是一种先进先出的数据结构。

image.png

//1:创建一个保存字符的队列
Queue<String> stringQueue = new LinkedList<String>();
//2:往消息队列中放入消息
stringQueue.offer("hello");
//3:从消息队列中取出消息并打印
System.out.println(stringQueue.poll());
复制代码

上面的代码演示了一个简单的队列。作用就是保存消息,取出消息。消息队列的本质就是一个消息的容器。消息的生产者产生消息放入队列,消息的消费者取出消息进行消费。

所以,kafka就是个二道贩子,把消息接进来,然后送出去。

消息队列的应用场景

  • 应用解耦

    应用和应用之间如果使用接口进行交互,这属于一种强耦合的调用关系,假如接口调用失败,则整个过程都失败。这里加入消息队列作为一个中转,调用者把调用接口的行为变为向消息队列发送消息,生产者发送成功后,他的使命就完成了。他不关心消息是否被及时消费。而消息的消费者在合适的时间取出消息进行消费即可。

  • 异步处理

    异步处理就是多应用对消息队列的同一消息进行处理,并发处理消息,比起串行处理,效率大大提高。

  • 限流削峰

    比如秒杀这种业务场景,用消息队列做一个容器,这个容器是能放十条消息(限制队列长度即可实现),后台只需要慢慢消费这十条消息即可,避免了大量请求直接涌向后台接口,把后台接口搞崩掉。

  • 消息驱动的系统

    系统分为消息队列,消息生产者,消息消费者,生产者负责生产消息,消费者(多个)负责对消息进行处理。就是一种系统设计理念。通过消息队列做到解耦合,也做到了缓冲,削峰的作用。

消息队列的两种方式

点对点模式
点对点模式包括三个角色

  • 消息队列
  • 发送者(生产者)
  • 接收者(消费者)

image.png

消息发送者发送消息,消息消费者消费消息,当消息被消费之后,队列中就不在保存消息。所以消息消费者不可能消费到已经被消费的消息。

发布/订阅模式

发布/订阅模式
发布/订阅模式包括三个角色:

  • 角色主题(Topic)
  • 发布者(Publisher)
  • 订阅者(Subscriber)

image.png

发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。
发布/订阅模式的特点:

  • 每个消息可以有多个订阅者。也就是一个消息可以被不同的订阅者消费。
  • 发布者和订阅者有时间上的依赖。针对某个Topic的订阅者,订阅者必须订阅之后才能消费该主题发布的消息。
  • 订阅者必须提前订阅该角色主题,并保持在线运行。

kafka基本情况

分布式,分区,多副本,多订阅这的日志系统(分布式MQ系统)。
发送消息者为Producer,消息接收者为Consumer。Kafka集群由多个kafka实例组成,每个实例(Server)叫做broker。无论是kafka集群,还是producer和consumer都依赖于Zookeeper来保证系统可用性,zk中保存了一些元(mate)信息。
kafka的特点:

  • 可靠性:分布式,分区,复制,容错
  • 可扩展性:kafka消息传递系统轻松缩放,无需停机
  • 耐用性:kafka使用分布式提交日志,这个以为这他会尽可能的快速将数据持久化到磁盘上,因此它是持久的。
  • 性能:kafka对于发布订阅和消息订阅都具有高吞吐量。

kafka架构

image.png

Kafka Cluster: 由多个实例组成cluster。每个实例(服务器)称为broker(掮客)

Kafka broker: kafka集群的每个实例。每个实例都有一个唯一的编号,起标识作用。

Kafka consumer: 消息的消费者,负责消费消息。

Kafka Topic: 主题,用来区分出不同的消息种类。存储消息的时候按种类区分,放入不同的topic下。比如向曾经的广播,每个台有一个频率,然后你要听某个台的话你需要把频率调到对应的频率上,这个频率就是topic。其实就是一个区分的作用。topic是一个逻辑划分单位。

shard: topic的分片。一般来说,不同的分片会放在不同的节点上(broker)。分片的数量理论上是没有上限的。对于一个topic,可以划分为多个小的容器,每个容器其实就是一个分片(分区),然后每个分区可以均匀的落在各个节点上。主要作用是在存储数据的时候,可以让数据在不同的分片上来存储,相当于将数据存储在不同的服务器中,从而达到提高topic存储容量的目的。

replicas: 副本,对每个分片构建多个副本,保证数据不会丢失。副本的上限就是节点的数量。比如kafka集群里有3个实例,那么最多只能设置3个副本。多个副本之间是存在主从关系的。主副本负责数据读写,从副本负责数据拷贝。不过在新版本2.0中有所变化。从副本在一定程度上可以进行读写。副本越多,数据越安全,同时对磁盘占用的空间越多。

kafka原理 分片和副本机制

一个消费者可以监听多个topic。
偏移量。
image.png

分片: 对一个topic(主题,理解为一个大容器即可),划分为多个小容器,每个小容器其实就是一个分片(分区),然后这些分片会均匀的落在各个broker上。在存储数据的时候,数据会存储在不同的分片上,也就是数据会落在不同的机器上,从而扩展了topic的存储容量。

副本: 对每个分片的数据复制多个副本,从而保证数据不容易丢失。需要注意的是,同分片的多个副本不能放在一个节点上,因为当这个节点挂掉,那么这些副本就都丢了。副本的目的就是为了防止丢失,所以需要保证副本的分散存储。所以副本的数量受限于节点的数量,副本的最大值只能和节点的最大值相等。

kafka数据不丢失原理(ack)

生产者端如何保证数据不丢失

生产者端是靠ack校验机制保证数据不丢失的。

ack的三个值(0,1,-1)

0:生产者只负责发送消息,不关心消息是否被kafka成功接收。

1:生产者需要保证数据成功发送到指定topic的分片的主副本上,然后kafka会给出ack响应。

-1(all):生产者需要确保消息成功发送到kafka指定topic的分片的所有副本中,并且都给出ack响应,才可以认为消息发送成功了。

broker端如何保证消息不丢失

broker端主要是通过数据的副本机制和ack为-1来保证数据不丢失。

消费端如何保证数据不丢失

image.png
1:消费者去连接kafka集群,kafka根据消费者的groupId找到其上次消费的位置(偏移量),如果该消费者是第一次消费,默认从监听的时间开始监听消息。(这里可以配置不同消费机制,也可以从头消费)

2:消费者开始获取数据,之后进行业务处理,然后提交偏移量给kafka。

这里会不会存在消息丢失呢?

答案是不会的!但是这里可能会存在消息重复消费的问题,因为如果当消息消费完成,然后没来得及提交偏移量,消费者挂了,那么下次消费的时候,kafka根据这个消费者groupId找上次消费的位置,而因为消费者上次没有提交偏移量,所以这里就会造成消息重复消费。

kafka的每个消费者组的偏移量信息都记录在哪里呢?

版本不同,记录的位置不同。

在0.8.x版本及之前,偏移量信息被记录在Zookeeper中
在0.8.x之后,偏移量被记录在kafka中,在kafka中专门有一个主题来进行统一的记录(_consumer_offsets 此topic有50个分区,每个分区一个副本)

kafka的存储机制

kafka中数据存储机制:以一个topic分片的副本为例:

image.png

index是索引文件,log是日志文件,数据记录在log中。index文件主要用于存储消息的偏移量在log文件的物理偏移量的信息。

kafka是一个消息中间件,当数据被消费了,此时这个数据就可以被认为是无用了,需要在某个时间点删除。

数据存储在副本中,副本被某个broker节点进行管理,最终的数据是存储在磁盘中,那么数据是存储在一个文件中还是分文件存储?

是分文件来存储的。每个文件存储1GB的数据。

在一个文件段中主要由两个文件构成。一个是index,一个是log。index是log的索引文件。

文件名是此文件存储消息的起始偏移量。

为什么kafka要进行分文件来存储数据呢?

1)保证每个文件不至于过大,这样读取效率会更高。

2)kafka仅仅是一个临时存储数据的中介,默认情况下kafka会删除过期数据(时间为7天)。如果放在一个文件中,删除时需要遍历文件内容,效率低,操作麻烦。分文件的话只需要用文件的最后修改时间判断即可。

Kafka的数据查询机制

image.png

上图是一个副本的数据,如何快速的找到777777这条数据呢?

1)确定数据所在的segment段

2)在这个段(737337)中先去查询index,从中找到777777消息在log文件中具体的物理偏移量

3)遍历log文件,顺序查找到具体位置,获取数据即可

kafka的生产者分区策略

image.png

假设,有一个topic,此topic有三个分片,三个副本。这是消息生产者生产的数据应该发往那个分片,或者所有的分片都会接收到消息吗?

消息只会发送给某一个分片的主副本,然后主副本将信息数据同步给其他两个从副本。

kafka中有四种生产者发送消息的分区策略:

1)hash取模

2)粘性分区(轮询)

3)指定分区方案

4)自定义分区方案

具体懒得写了。。。

kafka消费者的负载均衡策略

如果消息生产的速度远远大于消息消费的速度就会造成消息的积压,那么如何解决呢?

增加消费者数量(需要保证他们在同一组内才能达到提高消费速度的目的啊),这里需要注意的是,kafka的消费者负载均衡规定,在一个消费者组内,消费者的数量最多只能和监听topic的分片数量相等,如果消费者数据量大于了topic的分片数据量,那么总会有消费者处于闲置状态。且一个分片的数据,只能被一个消费者所消费,不能被组内其他消费者所消费。

如何使用kafka模拟点对点和发布订阅呢?

定义多个消费者,让消费者属于不同的group,订阅同一个topic即可,模拟发布订阅

让所有监听topic的消费者,都属于同一个消费者组即可模拟点对点

Kafka数据积压

(可以通过kafka-eagle查看)

Kafka配额限速机制

生产者和消费者以极高的速度生产/消费消息,从而占用broker的全部或者大量资源,造成网络IO饱和。会影响其他topic的正常运行。

配额(Quotas)就是为了解决这个问题。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享