消息中间件-Kafka1-实现原理

消息中间件-Kafka

一、kafka简介

1、概念
Kafka是最初由Linkedin公司开发,是一个分布式、支持分区(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、storm/Spark流式处理引擎,web/nginx日志、访问日志,消息服务等等,用scala语言编写,Linkedin于2010年贡献给了Apache基金会并成为顶级开源 项目。
2、Kafka特性

  • Kafka具有近乎实时性的消息处理能力,即使面对海量消息也能够高效地存储消息和查询消息。
    Kafka将消息保存在磁盘中,它以顺序读写的方式访问磁盘,从而避免了随机读写磁盘导致的性能瓶颈。
  • Kafka支持批量读写消息,并且会对消息进行批量压缩
  • Kafka支持消息分区,每个分区中的消息保证顺序传输,而分区之间则可以并发操作,具备高并发能力
  • Kafka也支持在线增加分区,支持在线水平扩展
  • Kafka支持为每个分区创建多个副本,其中只会有一个Leader副本负责读写,其他副本只负责与Leader副本进行同步,Kafka会将Leader副本均匀地分布在集群中的服务器上,实现性能最大化,同时具备较强的容灾能力

3、应用场景

  • 在应用系统中可以将Kafka作为传统的消息中间件,实现消息队列和消息的发布/订阅,在某些特定场景下其性能要更优于RabbitMQ、ActiveMQ等传统的消息中间件
  • Kafka也被用作系统中的数据总线,将其接入多个子系统中,子系统会将产生的数据发送到Kafka中保存,之后流转到目的系统中
  • Kafka还可以用作日志收集中心,多个系统产生的日志统一收集到Kafka中,然后由数据分析平台进行统一处理。日志会被Kafka持久化到磁盘,所以同时支持离线数据处理和实时数据处理
  • 事件溯源
    Kafka的持久化存储和顺序消息传递特性使其成为事件溯源的理想选择。通过将系统的事件以消息的形式写入Kafka的主题中,可以实现对系统状态的完全恢复和追溯。这对于需要满足合规性要求或实现事件溯源的系统非常重要,如金融交易系统、电子商务系统等。
  • 流媒体处理
    Kafka在流媒体处理领域也有着广泛的应用。流媒体处理要求系统能够高效地处理大规模的音视频数据流。Kafka的高吞吐量和低延迟特性使其成为一个理想的流媒体处理平台。通过使用Kafka,可以构建高性能的音视频处理系统,实现实时的流媒体传输、转码、存储和分发。

4、数据持久化
在分布式系统中,各个组件是通过网路连接起来的。一般认为网络传输是不可靠的,当数据在两个组件之间进行传递的时候,传输过程可能会失败。除非数据被持久化到磁盘,否则就可能造成消息的丢失。Kafka把数据以消息的形式持久化到磁盘,即使Kafka出现宕机,也可以保证数据不会丢失,通过这一方式规避了数据丢失风险。为了避免磁盘上的数据不断增长,Kafka提供了日志清理、日志压缩等功能,对过时的、已经处理完成的数据进行清除。在磁盘操作中,耗时最长的就是寻道时间,这是导致磁盘的随机I/O性能很差的主要原因。为了提高消息持久化的性能,Kafka采用顺序读写的方式访问,实现了高吞吐量。
5、扩展与容灾
Kafka的每个Topic(主题)都可以分为多个Partition(分区),每个分区都有多个Replica(副本),实现消息冗余备份。每个分区中的消息是不同的,这类似于数据库中水平切分的思想,提高了并发读写的能力。而同一分区的不同副本中保存的是相同的消息,副本之间是一主多从的关系,其中Leader副本负责处理读写请求,Follower副本则只与Leader副本进行消息同步,当Leader副本出现故障时,则从Follower副本中重新选举Leader副本对外提供服务。这样,通过提高分区的数量,就可以实现水平扩展;通过提高副本的数量,就可以提高容灾能力。
Kafka的容灾能力不仅体现在服务端,在Consumer端也有相关设计。Consumer使用pull方式从服务端拉
取消息,并且在Consumer端保存消费的具体位置,当消费者宕机后恢复上线,可以根据自己保存的消费位
置重新拉取需要的消息进行消费,这就不会造成消息丢失。也就是说,Kafka不决定何时、如何消费消息,
而是Consumer自己决定何时、如何消费消息。
Kafka还支持Consumer的水平扩展能力。我们可以让多个Consumer加入一个Consumer Group(消费组),在一个Consumer Group中,每个分区只能分配给一个Consumer消费,当Kafka服务端通过增加分区数量进行水平扩展后,我们可以向Consumer Group中增加新的Consumer来提高整个Consumer Group的消费能力。当Consumer Group中的一个Consumer出现故障下线时,会通过Rebalance操作将下线Consumer负责处理的分区分配给其他Consumer继续处理;当下线Consumer重新上线加入Consumer Group时,会再进行一次Rebalance操作,重新分配分区。当然,一个Consumer Group可以订阅很多不同的Topic,每个Consumer可以同时处理多个分区
6、分区数据的顺序保证
Kafka保证一个分区内的消息的有序性,但是并不保证多个partition之间的数据有顺序。
7、异步通信
Kafka为系统提供了异步处理能力。例如,两个系统需要通过网络进行数据交换,其中一端可以把一个消息放入Kafka中后立即返回继续执行其他路基,不需要等待对端的响应。待后者将处理结果放入Kafka中之后,前者可以从其中获取并解析响应。

二、Kfaka核心概念

  • 消息
    消息是Kafka中最基本的数据单元。消息由一串字节构成,其中主要由key和value构成,key和value也都是byte数组。key的主要作用是根据一定的策略,将此消息路由到指定的分区中,这样就可以保证包含同一key的消息全部写入同一分区中,key可以是null。
  • Topic/分区/Log
    Topic是用于存储消息的逻辑概念,可以看作一个消息集合。每个Topic可以有多个生产者向其中推送(push)消息,也可以有任意多个消费者消费其中的消息。每个Topic可以划分成多个分区(每个Topic都至少有一个分区),同一Topic下的不同分区包含的消息是不同的。每个消息在被添加到分区时,都会被分配一个offset,它是消息在此分区中的唯一编号,Kafka通过offset保证消息在分区内的顺序,offset的顺序性不跨分区,即Kafka只保证在同一个分区内的消息是有序的;同一Topic的多个分区内的消息,Kafka并不保证其顺序性。同一Topic的不同分区会分配在不同的Broker上。分区是Kafka水平扩展性的基础,我们可以通过增加服务器并在其上分配Partition的方式来增加Kafka的并行处理能力。
    分区在逻辑上对应着一个Log,当生产者将消息写入分区时,实际上是写入到了分区对应的Log中。Log是一个逻辑概念,可以对应到磁盘上的一个文件夹。Log由多个Segment组成,每个Segment对应一个日志文件和索引文件。在面对海量数据时,为避免出现超大文件,每个日志文件的大小是有限制的,当超出限制后则会创建新的Segment,继续对外提供服务。这里要注意,因为Kafka采用顺序I/O,所以只向最新的Segment追加数据。
  • 保留策略与日志压缩
    无论消费者是否已经消费了消息,Kafka都会一直保存这些消息,但并不会像数据库那样长期保存。为了避免磁盘被占满,Kafka会配置相应的“保留策略”(retention policy),以实现周期性地删除陈旧的消息。

一种是根据消息保留的时间,当消息在Kafka中保存的时间超过了指定时间,就可以被删除
根据Topic存储的数据大小,当Topic所占的日志文件大小大于一个阈值,则可以开始删除最旧的消息。

Kafka会启动一个后台线程,定期检查是否存在可以删除的消息。“保留策略”的配置是非常灵活的,可以有全局的配置,也可以针对Topic进行配置覆盖全局配置。

  • 消息压缩
    在很多场景中,消息的key与value的值之间的对应关系是不断变化的,就像数据库中的数据会不断被修改一样,消费者只关心key对应的最新value值。此时,可以开启Kafka的日志压缩功能,Kafka会在后台启动一个线程,定期将相同key的消息进行合并,只保留最新的value值。
    压缩过程:
    在这里插入图片描述
  • Broker
    一个单独的Kafka服务器就是一个Broker。Broker的主要工作就是接收生产者发过来的消息,分配offset,之后保存到磁盘中;同时,接收消费者、其他Broker的请求,根据请求类型进行相应处理并返回响应。在一般的生产环境中,一个Broker独占一台物理服务器。
  • 分区副本
    每个分区的副本集合中,都会选举出一个副本作为Leader副本,Kafka在不同的场景下会采用不同的选举策略所有的读写请求都由选举出的Leader副本处理,其他都作为Follower副本,Follower副本仅仅是从Leader 副本处把数据拉取到本地之后,同步更新到自己的Log中。一般情况下,同一分区的多个副本会被分配到不同的Broker上,这样,当Leader所在的Broker宕机之后,可以重新选举新的Leader,继续对外提供服务。
  • ISR(In-Sync Replica)集合
    ISR(In-Sync Replica)集合表示的是目前“可用”(alive)且消息量与Leader相差不多的副本集合,其中每个副本必须满足副本所在节点必须维持着与ZooKeeper的连接副本最后一条消息的offset与Leader副本的最后一条消息的offset之间的差值不能超出指定的阈值*
    每个分区中的Leader副本都会维护此分区的ISR集合。写请求首先由Leader副本处理,之后Follower副本会从Leader上拉取写入的消息,这个过程会有一定的延迟,导致Follower副本中保存的消息略少于Leader副本,只要未超出阈值都是可以容忍的。如果一个Follower副本出现异常,比如:宕机,发生长时间GC而导致Kafka僵死或是网络断开连接导致长时间没有拉取消息进行同步,就会违反上面的两个条件,从而被Leader副本踢出ISR集合。当Follower副本从异常中恢复之后,会继续与Leader副本进行同步,当Follower副本“追上”(即最后一条消息的offset的差值小于指定阈值)Leader副本的时候,此Follower副本会被Leader副本重新加入到ISR中。
  • HW
    HW(HighWatermark)和LEO与上面的ISR集合紧密相关。HW标记了一个特殊的offset,当消费者处理消息的时候,只能拉取到HW之前的消息,HW之后的消息对消费者来说是不可见的。与ISR集合类似,HW也是由Leader副本管理的。当ISR集合中全部的Follower副本都拉取HW指定消息进行同步后,Leader副本会递增HW的值。
  • LEO(Log End Offset)
    LEO是所有的副本都会有的一个offset标记,它指向追加到当前副本的最后一个消息的offset。当生产者向Leader副本追加消息的时候,Leader副本的LEO标记会递增;当Follower副本成功从Leader副本拉取消息并更新到本地的时候,Follower副本的LEO就会增加。

HW与LEO的关系如下图
在这里插入图片描述
①Producer向此Partition推送消息。
②Leader副本将消息追加到Log中,并递增其LEO。
③Follower副本从Leader副本拉取消息进行同步。
④Follower副本将拉取到的消息更新到本地Log中,并递增其LEO。
⑤当ISR集合中所有副本都完成了对offset=11的消息的同步,Leader副本会递增HW。
在①~⑤步完成之后,offset=11的消息就对生产者可见了。

  • 为什么kafka数据冗余要设计成这样?
    常见的数据同步包括同步复制和异步复制。
    同步复制要求所有能工作的Follower副本都复制完,这条消息才会被认为提交成功。一旦有一个
    Follower副本出现故障,就会导致HW无法完成递增,消息就无法提交,生产者获取不到消息。这
    种情况下,故障的Follower副本会拖慢整个系统的性能,甚至导致整个系统不可用。
    异步复制中,Leader副本收到生产者推送的消息后,就认为此消息提交成功。Follower副本则异步
    地从Leader副本同步消息。这种设计虽然避免了同步复制的问题,但同样也存在一定的风险。现在
    假设所有Follower副本的同步速度都比较慢,它们保存的消息量都远远落后于Leader副本。
    在这里插入图片描述
    此时Leader副本所在的Broker突然宕机,则会重新选举新的Leader副本,而新Leader副本中没有原来
    Leader副本的消息,这就出现了消息的丢失,而有些消费者则可能消费了这些丢失的消息,状态变得不可控。
    Kafka权衡了同步复制和异步复制两种策略,通过引入了ISR集合,巧妙地解决了上面两种方案存在的
    缺陷:当Follower副本的延迟过高时,Leader副本被踢出ISR集合,消息依然可以快速提交,生产者可以快速得到响应,避免高延时的Follower副本影响整个Kafka集群的性能。当Leader副本所在的Broker突然宕机的时候,会优先将ISR集合中Follower副本选举为Leader副本,新Leader副本中包含了HW之前的全部消息,这就避免了消息的丢失。值得注意是,Follower副本可以批量地从Leader副本复制消息,这就加快了网络I/O,Follower 副本在更新消息时是批量写磁盘,加速了磁盘的I/O,极大减少了Follower与Leader的差距。
  • Cluster(集群)与Controller(指挥中心)
    多个Broker可以做成一个Cluster(集群)对外提供服务,每个Cluster当中会选举出一个Broker来担任
    Controller,Controller是Kafka集群的指挥中心,而其他Broker则听从Controller指挥实现相应的功能。
    Controller负责管理分区的状状态、管理每个分区的副本状态、监听Zookeeper中数据的变化等工作。
    Controller也是一主多从的实现,所有Broker都会监听Controller Leader的状态,当Leader Controller出现故障时则重新选举新的Controller Leader。
  • 生产者
    生产者(Producer)的主要工作是生产消息,并将消息按照一定的规则推送到Topic的分区中。这里选
    择分区的“规则”可以有很多种,例如:根据消息的key的Hash值选择分区,或按序轮询全部分区的方式。
  • 消费者
    消费者(Consumer)的主要工作是从Topic中拉取消息,并对消息进行消费。某个消费者消费到
    Partition的哪个位置(offset)的相关信息,是Consumer自己维护的。 如下图
    在这里插入图片描述
  • Consumer Group 消费者组
    在Kafka中,多个Consumer可以组成一个Consumer Group,一个Consumer只能属于一个Consumer
    Group。Consumer Group保证其订阅的Topic的每个分区只被分配给此Consumer Group中的一个消费者处理。如果不同Consumer Group订阅了同一Topic,Consumer Group彼此之间不会干扰。这样,如果要实现一个消息可以被多个消费者同时消费(“广播”)的效果,则将每个消费者放入单独的一个Consumer Group;如果要实现一个消息只被一个消费者消费(“独占”)的效果,则将所有Consumer放入一个Consumer Group中。
    消费者组消费消息如图:
    在这里插入图片描述
    Consumer Group除了实现“独占”和“广播”模式的消息处理,Kafka还通过Consumer Group实现了消费者的水平扩展和故障转移。在上图中,当Consumer3的处理能力不足以处理两个Partition中的数据时,可以通过向Consumer Group中添加消费者的方式,触发Rebalance操作重新分配分区与消费者的对应关系,从而实现水平扩展。如下图所示,添加Consumer4之后,Consumer3只消费Partition2中的消息,Partition3中的消息则由Consumer4来消费。
    在这里插入图片描述
    下面来看消费者出现故障的场景,当Consumer4宕机时,Consumer Group会自动重新分配分区,如下图所示,由Consumer3接管Consumer4对应的分区继续处理。
    在这里插入图片描述
    注,Consumer Group中消费者的数量并不是越多越好,当其中消费者数量超过分区的数量时,会导
    致有消费者分配不到分区,从而造成消费者的浪费

三、Kafak消息处理流程图

  • 单个Kafka Server单体模式
    在这里插入图片描述
    Kafka的每个Topic(主题)都可以分为多个Partition(分区),每个分区都有多个Replica(副本),实现消息冗余备份。每个分区中的消息是不同的,这类似于数据库中水平切分的思想,提高了并发读写的能力。而同一分区的不同副本中保存的是相同的消息,副本之间是一主多从的关系,其中Leader副本负责处理读写请求,Follower副本则只与Leader副本进行消息同步,当Leader副本出现故障时,则从Follower副本中重新选举Leader副本对外提供服务。
  • 集群Kafak Server 集群模式
    在这里插入图片描述
    如上所示,生产者会根据业务逻辑产生消息,之后根据路由规则将消息发送到指定分区的Leader副本所在的Broker上。在Kafka服务端接收到消息后,会将消息追加到Log中保存,之后Follower副本会与
    Leader副本进行同步,当ISR集合中所有副本都完成了此消息的同步后,则Leader副本的HW会增加,并向生产者返回响应。
    当消费者加入到Consumer Group时,会触发Rebalance操作将分区分配给不同的消费者消费。随后,消费者会恢复其消费位置,并向Kafka服务端发送拉取消息的请求,Leader副本会验证请求的offset以及其他相关信息,最后返回消息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/929146.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

protobuf实现Hbase数据压缩

目录 前置HBase数据压缩效果获取数据(反序列化) 前置 安装说明 使用说明 HBaseDDL和DML操作 HBase数据压缩 问题 在上文的datain中原文 每次写入数据会写入4个单元格的内容,现在希望能对其进行筛减,合并成1格,减少存储空间(序列…

爬虫专栏第二篇:Requests 库实战:从基础 GET 到 POST 登录全攻略

简介:本文聚焦 Requests 库的强大功能与应用实战。首先介绍其安装步骤及版本选择要点,随后深入讲解 GET 请求,以百度页面为例,展示如何发起基本 GET 请求、巧妙添加 headers 与参数以精准搜索,以及正确设置 encoding 避…

【Leetcode】19. 删除链表的第N个节点

【Leetcode】19. 删除链表的第N个节点 1. 题目介绍2. 方法一:计算链表长度逻辑流程:代码复杂度分析 1. 题目介绍 题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1: 输入:head [1,2,…

工业齐套管理虚拟现实仿真模拟软件

工业齐套管理虚拟现实仿真模拟软件是与法国最大的汽车制造商合作开发的一款虚拟现实仿真模拟软件,借助身临其境的虚拟现实环境,无需停止生产线,即可模拟仓库和提货区域。 工业齐套管理虚拟现实仿真模拟软件不仅适用于汽车工业,安全…

【嘟嘟早教卡】 小程序源码分享带后台管理

【嘟嘟早教卡】是专门为 3-6 岁婴幼儿童学习普通话、英语研发的早教启蒙认知识字的小程序 小程序由 Taro 及 Tailwind CSS 构建而成,后台管理使用 Laravel 及 Tailwind CSS 想法源于小时候玩的认知卡片,基本大部分家庭都买过认知卡片,我按照…

概率论相关知识随记

作为基础知识的补充,随学随记,方便以后查阅。 概率论相关知识随记 期望(Expectation)期望的定义离散型随机变量的期望示例:掷骰子的期望 连续型随机变量的期望示例:均匀分布的期望 期望的性质线性性质期望的…

FastAPI 响应状态码:管理和自定义 HTTP Status Code

FastAPI 响应状态码:管理和自定义 HTTP Status Code 本文介绍了如何在 FastAPI 中声明、使用和修改 HTTP 状态码,涵盖了常见的 HTTP 状态码分类,如信息响应(1xx)、成功状态(2xx)、客户端错误&a…

oracle 11g中如何快速设置表分区的自动增加

在很多业务系统中,一些大表一般通过分区表的形式来实现数据的分离管理,进而加快数据查询的速度。分区表运维管理的时候,由于人为操作容易忘记添加分区,导致业务数据写入报错。所以我们一般通过配置脚本或者利用oracle内置功能实现…

机器学习深入剖析逻辑回归算法

一、引言 在机器学习领域,逻辑回归(Logistic Regression)是一种极为经典且应用广泛的算法。尽管其名称带有 “回归” 二字,但实际上它主要用于解决分类问题,并且在众多领域都发挥着重要作用。接下来,让我们…

如何加强游戏安全,防止定制外挂影响游戏公平性

在现如今的游戏环境中,外挂始终是一个困扰玩家和开发者的问题。尤其是定制挂(Customized Cheats),它不仅复杂且隐蔽,更能针对性地绕过传统的反作弊系统,对游戏安全带来极大威胁。定制挂通常是根据玩家的需求…

6.824/6.5840 Lab 1: MapReduce

宁静的夏天 天空中繁星点点 心里头有些思念 思念着你的脸 ——宁夏 完整代码见: https://github.com/SnowLegend-star/6.824 由于这个lab整体难度实在不小,故考虑再三还是决定留下代码仅供参考 6.824的强度早有耳闻,我终于也是到了挑战这座高…

解决Jupyter Notebook无法转化为Pdf的问题(基于Typora非常实用)

笔者在完成各项作业和做笔记时,经常用到jupyter notebook;其因为可以同时运行python并提供格式化的数字公式的输入方式,得到了广大用户的喜爱。 当我们想要将.ipynb文件导出为pdf时,有两种常用方法。 1.Ctrlp 2.通过File ->…

[在线实验]-RabbitMQ镜像的下载与部署

镜像下载 docker的rabbitmq镜像资源-CSDN文库 加载镜像 docker load --input rabbitmq.tar 给镜像打标签 这里发现镜像名为none,需要给镜像重命名下 docker tag [镜像id] [新镜像名称]:[新镜像标签] docker tag ebaf409ffbe2 rabbitmq:management 运行镜像…

【JVM】—G1 GC日志详解

G1 GC日志详解 ⭐⭐⭐⭐⭐⭐ Github主页👉https://github.com/A-BigTree 笔记链接👉https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以,麻烦各位看官顺手点个star~😊 文章目录 G1 GC日志详解1 G1 GC周期2 G1日…

ADBC 查询语法介绍:EXECUTE_QUERY

可使用 CL_SQL_STATEMENT 类的以下实例方法执行查询: EXECUTE_QUERY 该方法有一个字符串类型的强制输入参数 STATEMENT,必须向其传递语法正确的 SELECT 语句。与 DML 语句一样,SET_PARAM 方法可用于将 ABAP 数据对象绑定到占位符。 查询结…

线程信号量 Linux环境 C语言实现

既可以解决多个同类共享资源的互斥问题&#xff0c;也可以解决简易的同步问题 头文件&#xff1a;#include <semaphore.h> 类型&#xff1a;sem_t 初始化&#xff1a;int sem_init(sem_t *sem, int pshared, unsigned int value); //程序中第一次对指定信号量调用p、v操…

springboot+mybatis对接使用postgresql中PostGIS地图坐标扩展类型字段

方案一&#xff08;完全集成和自动解析&#xff09;&#xff1a; <dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId></dependency> 使用 org.postgresql.geometric包下的 PGpoint 类来接收数据库中POINT…

21个Python脚本自动执行日常任务(1)

引言 作为编程领域摸爬滚打超过十年的老手&#xff0c;我深刻体会到&#xff0c;自动化那些重复性工作能大大节省我们的时间和精力。 Python以其简洁的语法和功能强大的库支持&#xff0c;成为了编写自动化脚本的首选语言。无论你是专业的程序员&#xff0c;还是希望简化日常工…

【Python网络爬虫笔记】6- 网络爬虫中的Requests库

一、概述 Requests 是一个用 Python 语言编写的、简洁且功能强大的 HTTP 库。它允许开发者方便地发送各种 HTTP 请求&#xff0c;如 GET、POST、PUT、DELETE 等&#xff0c;并且可以轻松地处理请求的响应。这个库在 Python 生态系统中被广泛使用&#xff0c;无论是简单的网页数…

网站维护记录

服务器重启&#xff0c;网站打不开&#xff1a;chown -R manager:manager /run/php-fpm/www.sock wordpress升级需设置ftp&#xff1a; // 设置权限0777 //define("FS_METHOD", "direct"); //define("FS_CHMOD_DIR", 0777); //define("…