浅谈消息队列 kafka

消息队列 kafka 了解一下

消息队列是什么

MQ真正的目的是为了通讯,屏蔽在层复杂的通讯协议定义了一套应用层的、更加简单的通讯协议,MQ 所要做的就是在底层协议上构建一个简单的生产者消费者模型,然后提供一个 SDK 给我们可以定义自己的生产者和消费者实现消息通讯和无视底层通讯协议

什么是 Kafka官网描述

号称全球100强的80%的企业都在用,包括制造业,银行,保险,通讯的大公司

Apache Kafka是一个开源的分布式事件流平台,被数千家公司用于高性能数据管道、流分析、数据集成和任务关键型应用程序。

与其他的 MQ 的一些区别

请添加图片描述

  • 重 Topic, Topic 是主题的意思,也就是我一个 Broken 里面有多个 Topic ,不同的 Topic 中是收不到消息的,Kafka 非常重视这种模式
  • 无 Broken ,那什么是无 Broken 呢,就是在生产者和消费者之间用一个类似 Socket 的方式进行传输,就不需要 Broken 了。
  • 多生产者消费者,也就是组的概念
  • 基于磁盘的数据存储
  • 伸缩性(可水平扩展)和高性能

Kafka 的应用场景

  • 消息队列
  • 日志收集
  • 用户活动跟踪
  • 流式处理:分布式,高吞吐量,速度快

Kafka 的架构图

Kafka 架构图

[image:6103CED4-5F06-42D6-BAFC-BAFD9C28AE8D-60890-00000DA6DC3A9E93/截屏2021-12-10 16.31.31.png]

只有一个生产者和一个消费者的模式
(1)ZooKeeper:Zookeeper 负责保存 broker 集群元数据,并对控制器进行选举等操作。
(2)Producer:生产者负责创建消息,将消息发送到 Broker。
(3)Broker: 一个独立的 Kafka 服务器被称作 broker,broker 负责接收来自生产者的消息,为消息设置偏移量,并将消息存储在磁盘。broker 为消费者提供服务,对读取分区的请求作出响应,返回已经提交到磁盘上的消息。
(4)Consumer:消费者负责从 Broker 订阅并消费消息。

在这里插入图片描述

(5)Consumer Group:Consumer Group 为消费者组,一个消费者组可以包含一个或多个 Consumer 。Producer Group:为生产者组,一个生产者组可以包含一个或多个 。
使用 多分区 + 多消费者 方式可以极大 提高数据下游的处理速度,同一消费者组中的消费者不会重复消费消息,同样的,不同消费组中的消费者消费消息时互不影响。
(6)Topic:Kafka 中的消息 以 Topic 为单位进行划分,生产者将消息发送到特定的 Topic,而消费者负责订阅 Topic 的消息并进行消费。
(7)Partition:一个 Topic 可以细分为多个分区,每个分区只属于单个主题。同一个主题下不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的 日志(Log)文件,消息在被追加到分区日志文件的时候都会分配一个特定的 偏移量(offset)
(8)Offset:offset 是消息在分区中的唯一标识,Kafka 通过它来保证消息在分区内的顺序性,不过 offset 并不跨越分区,也就是说,Kafka保证的是分区有序性而不是主题有序性

消息的同步提交和异步提交方法

  • 自动提交:消费者从 broker 中拿到消息之后立马把 offset 提交
  • 手动提交:消费者从 broker 中拿到消息之后不会立马提交 offset,而是等消费完成了之后才会提交
    1、手动同步提交:当消费者消费完消息后才调用同步提交方法,当集群返回 ack 之前一直阻塞,返回 ack 之后才提交成功。
    2、手动异步提交:在消费者消费完后调用异步的方法,不需要集群返回 ack ,即可执行之后的逻辑

Kafka 如何防止消息丢失和重复消费的

在防止消息丢失的方案中,如果生产者发送完消息后,由于网络问题,没有收到 Broken 的ack确认报文,那么它会重新发送,所以这个时候就会有两条相同的消息被消费者重复消费到。

  • 在上游把 生产者的重试关闭,但是会造成消息丢失
  • 在下游的消费者端解决幂等性问题:(结合具体业务分析)
    1、数据库唯一性主键,不会重复插入
    2、redis 中的set

幂等性的特点是其任意多次执行所产生的影响均与一次执行的影响相同,也就是不管你调用这个接口多少次,数据都不会发生改变

Kafka 的存储机制

请添加图片描述

请添加图片描述

  • 第一步就是根据 offset 先找到对应的 segment 文件
  • 第二步就是通过索引文件找到某一个具体的消息的物理地址

请添加图片描述

这套机制是建立在offset为有序的基础上,利用 segment +有序offset+稀疏索引+二分查找+顺序查找
等多种手段来高效的查找数据!

Kafka 如何做到高吞吐量和高性能

1、页缓存

Kafka是基于操作系统的页缓存来实现文件写入的。
操作系统本身有一层缓存,叫做page cache,是在内存里的缓存,我们也可以称之为os cache,意思就是操作系统自己管理的缓存。
请添加图片描述
Kafka在写入磁盘文件的时候,可以直接写入这个os cache里,也就是仅仅写入内存中,接下来由操作系统自己决定什么时候把os cache里的数据真的刷入磁盘文件中,所以就是在写内存而不是写磁盘。

操作系统会在程序主动调用 flush() 的时候才把数据真正的写到硬盘。如果Kafka写入到 cache 之后就立即 flush 然后再返回Producer叫同步;写入cache 之后立即返回 Producer 不调用flush叫异步

2、磁盘顺序读写

kafka写数据的时候,是以磁盘顺序写的方式来写的。也就是说,仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据,那么 Consumer从broker 读取数据时,因为自带了偏移量,接着上次读取的位置继续读,以此实现顺序读。

因为完成一次磁盘 IO,需要经过寻道旋转数据传输三个步骤,所以普通的机械磁盘如果你要是随机写的话,确实性能极差,也就是随便找到文件的某个位置来写数据。但是如果你是追加文件末尾按照顺序的方式来写数据的话,就省去了寻道和旋转的次数,那么这种磁盘顺序写的性能基本上可以跟写内存的性能相差无几。

在操作系统看来两个逻辑上连续的扇区(sector)未必在物理上就是连续的,因为读写都是物理地址映射出的基于虚拟地址

请添加图片描述

根据kafka官网的说法,6个7200转的磁盘组成raid5,顺序写的速度能达到(600MB/S),而随机读写速度仅为100kb/s

3、零拷贝

请添加图片描述
一次是从操作系统的 cache 里拷贝到应用进程的缓存里,接着又从应用程序缓存里拷贝回操作系统的 Socket 缓存里
而且为了进行这两次拷贝,中间还发生了好几次上下文切换,一会儿是应用程序在执行,一会儿上下文切换到操作系统来执行。所以这种方式来读取数据是比较消耗性能的。
请添加图片描述
零拷贝技术,通常是指计算机在网络上发送文件时,不需要将文件内容拷贝到用户空间(User Space)而直接在内核空间(Kernel Space)中传输到网络的方式。也就是说,直接让操作系统的 cache 中的数据发送到网卡后传输给下游的消费者,中间跳过了两次拷贝数据的步骤

那么,零拷贝是怎么实现的呢?

DMA(Direct Memory Access,直接存储器访问,将数据从一个地址空间复制到另外一个地址空间,也就是 磁盘到缓存缓存到网卡

1、通过 DMA 将文件拷贝到内核缓冲区中;
2、向socket 缓存中追加当前要发生的数据在内核缓冲区中的位置和偏移量
3、根据socket 缓存中的位置和偏移量直接将内核缓冲区的数据通过 DMA 拷贝到网卡设备中;

在 C 语言层面上通过该函数实现:

//根据 cache 中的位置和偏移量拷贝
sendfile(socket, file, len);

Linux 中一切皆为文件

所以这样通过零拷贝可以减少甚至完全避免不必要的CPU拷贝,减少内存带宽的占用,减少用户空间和操作系统内核空间之间的上下文切换

那 Kafka 是如何保障它的可靠性的呢

副本数据同步策略

请添加图片描述
副本是相对partition而言的,一个分区中包含一个或多个副本,其中一个为 leader副本,其余为follower副本,各个副本位于不同的broker节点中。所有的读写操作都是经过Leader进行的,同时follower会定期地去leader上复制数据。
当Leader挂掉之后,其中一个follower会重新成为新的Leader.通过分区副本,引入了数据冗余。

Kafka的分区多副本架构是Kafka可靠性保证的核心,把消息写入多个副本可以使Kafka在发生崩溃时仍能保证消息的持久性。

ISR机制

AR: 分区中的所有副本统称为AR(Assigned Repllicas)。

ISR : 在分区中,所有副本统称为AR, Leader维护了一个动态的in-sync
replica(ISR)
,ISR是指与leader副本保持同步状态的副本集合。当然leader副本本身也是这个集合中的一员。

当ISR中的follower完成数据同步之后, leader就会给follower发送ack,如果其中一个follower长时间未向leader同步数据,该follower将会被踢出ISR集合,当leader发生故障后,就会从ISR集合中重新选举出新的leader

OSR : 与leader副本同步滞后过多,也就是掉队的副本(不包括leader),组成OSR(Out-Sync Relipcas)。在正常情况下,所有的 follower 副本都应该与 leader 副本保持一定程度的同步,即 当 AR = ISR , OSR 集合为空。

HW : HW 是High Watermak的缩写, 俗称高水位,它表示了一个特定消息的偏移量(offset),取 patition 对应的 ISR 中最小的 LEO 作为 HW,消费者只能拉取到这个offset之前的消息

LEO : LEO 是Log End Offset的缩写,它表示了当前日志文件中下一条待写入消息的 offset。

请添加图片描述

那么现在的 Kafka 的选举机制是怎么的呢

1、Controller :在Kafka集群中会有一个或者多个broker,其中有一个broker会被选举为控制器(基于 Zookeeper),它负责管理整个集群中所有分区和副本的状态。

如何推举出 Controller 呢,在 zeekeeper 中,临时节点注册的前面的节点就是 leader,如果该 Controller 挂了,那么排在它下一个节点就成为一个新的 leader。

2、 Partition副本选举Leader机制

controller 监听到分区 leader 所在的 broker 挂了,那么 controller 会从ISR 列表里挑第一个 broker 作为 leader (第一个 broker 最先放进ISR列表,可能是同步数据最多的副本),当 ISR 列表里所有副本都挂了的时候可以在 ISR 列表以外的副本中选leader,这种设置,可以提高可用性,但是选出的新leader有可能数据少很多。

请添加图片描述

ack应答机制

为保证producer发送的数据,能可靠的达到指定的topic,Producer提供了消息确认机制。生产者往Broker的topic中发送消息时,可以通过配置来决定有几个副本收到这条消息才算消息发送成功。可以在定义Producer时通过acks参数指定,这个参数支持以下三种值:

(1) acks=0: producer不会等待任何来自broker的响应特点:低延迟,高吞吐,数据可能会丢失。

如果当中出现问题,导致broker没有收到消息,那么producer无从得知,会造成消息丢失。

(2) acks=1 (默认值) :只要集群中partition的Leader节点收到消息,生产者就会收到一个来自服务器的成功响应。

如果在follower同步之前, leader出现故障,将会丢失数据。

(3) acks–1:只有当所有参与复制的节点全部都收到消息时,生产者才会收到一个来自服务器的成功响应。

这种模式是最安全的,不过需要牺牲性能。根据实际的应用场景,选择设置不同的acks,以此保证数据的可靠性

Producer发送消息还可以选择同步或异步模式,如果设置成异步,虽然会极大的提高消息发送的性能,但是这样会增加丢失数据的风险。如果需要确保消息的可靠性,必须将设置为同步

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值