为什么使用消息队列?

  1. 解耦
    • 我以我的一段开发经验举例:

    【Kafka】登录日志处理的三次阶梯式优化实践:从同步写入到Kafka多分区批处理
    我做过一个登录日志逻辑,就是在登录逻辑末尾,加一段写进数据库登录日志表的逻辑,那么,如果我们啥都不用,就单纯同步写入(就是在login函数返回之前加一段写入逻辑),那么会拖慢login的操作,在高并发时,影响系统性能。

    • 如果我们把写入逻辑异步实现,就可以形成,先让用户感知到登录成功的效果,对登录日志的写入我们放到后台执行,这样的解耦形式。
    • 那就要用到消息队列了,这时,简单一点,我们可以利用go的channl,快速搭建一个简易的消息队列,但是你自己写的很多功能是比不上kafka好使的,所以用kafka作为消息队列,是更好的选择。

Kafka 是基于主题(Topic)进行消息发布与订阅的模型,实现生产者和消费者之间松散耦合

  1. 削峰填谷
    • 应对突发流量(如秒杀活动)时,消息队列可暂存超出下游服务处理能力的请求,下游服务按自身节奏消费,避免因流量峰值直接压垮系统。
  2. 异步处理
    • 非核心流程(如通知推送、数据统计)从主流程中剥离,通过消息队列异步处理,减少主流程阻塞
  3. 容错与持久化
    • 应对分布式系统中,某个上游节点/服务宕机时下游服务来不及处理其最后发出的数据,导致数据丢失的情况。
    • 如果有一个队列做缓冲,那么他宕机前的所有发出数据,都可以暂存在这个队列中,等候处理。
  4. 数据流处理与实时分析(万流归中)
    • 将多个服务产生的数据汇聚,方便实时分析
  5. 广播与多订阅模式
    • 一个生产者发布的消息需要被多个消费者处理,单纯的点对点模式无法满足,需要kafka的订阅发布模式

    设置多个消费者组,每个消费者组中的一个消费者,可以分别处理一次消息

解耦、削峰填谷、异步处理、容错与持久化、数据流处理与实时分析、广播与多订阅模式


Kafka 架构原理

1. Broker

  • Broker 是 Kafka 的服务器实例,负责接收、存储和传输消息。Kafka 集群由一个或多个 Broker 组成,通常每个 Broker 是一个独立的物理或虚拟服务器。
  • 每个 Broker 都可以存储多个 Topic 的数据,并为这些数据提供读取服务。Kafka 的分布式特性允许将数据分布在不同的 Broker 上,以实现水平扩展。

2. Producer(生产者)

  • Producer 是消息的发送者,负责将数据发布到 Kafka 中的 Topic
  • Producer 可以指定消息发送到某个 Partition,也可以通过轮询或基于特定规则(如基于键的哈希值)来选择 Partition。

3. Consumer(消费者)

  • Consumer 是消息的读取者,负责从 Kafka 的 Topic 中订阅并读取消息。
  • Consumer 组的概念允许多个 Consumer 实例组成一个组,来平衡消费不同 Partition 的消息。

4. Topic 和 Partition

  • Topic 是 Kafka 中消息的分类单位,类似于数据库中的表。每个 Topic 可以有多个 Partition,而 Partition 是 Kafka 的并行处理单位。
  • 每个 Partition 是一个有序的、不可变的日志文件,每条消息在 Partition 中都有一个唯一的偏移量(offset)。Partition 保证了顺序性,而不同 Partition 之间可以并行处理。

5. Zookeeper / Raft(控制器)

  • Kafka 使用 Zookeeper 来管理集群元数据、协调 Broker 和维护 Partition 的 Leader 选举过程。
  • 新的 Kafka 版本可以使用 KRaft 协议来替代 Zookeeper,用于集群控制和选举 Leader。

关于Raft协议
是一种针对主节点宕机时,从节点如何快速选举出新主节点的分布式一致性协议。

核心解决3个问题:

  1. 从节点如何快速感知主节点宕机?
  • 主节点会定期广播心跳,从节点接收后重置自身内置计数器。
  • 若计数器归零前未收到心跳,从节点即判定主节点宕机。
  1. 如何选举新主节点?
  • 感知宕机的从节点切换为候选者,向所有节点广播"请求投票"
  • 其他节点收到后进行投票,获得大多数节点支持的候选者成为新主节点。
  1. 为什么从节点计数器要设为随机值,而非统一短时间?
  • 若计数器统一,所有从节点会同时感知宕机并争当候选者,导致投票分散,需多次重试,降低效率。
  • 随机计数器可让部分节点更早发起选举,优先获得多数票,实现快速选主。

补充

  • 任期(Term):每个选举周期的唯一标识(递增整数),确保每次选举在新任期内进行,避免旧投票干扰。
  • 投票原则一任期内仅投一票,且优先给日志更新的候选者投票(保证数据一致性)。

6. Leader 和 Follower

Kafka 通过 Partition 副本机制保证数据的高可用性

副本机制:每个 partition 有多份 replica,分为 Leader 和 Follower

(且副本的数量不能大于Broker的数量followerleader绝对是在不同的机器同一机器对同一个分区也只可能存放一个副本(包括自己)。)

  • 每个 Partition 都有一个 Leader,负责处理所有的读写请求。其他副本称为 Follower,它们从 Leader 同步数据。

围绕leader和follower,可以引出三种ACK机制,在配置partition时,分别决定了不同级别的消息可靠性

  1. acks=0:Producer 只管发 不管 Broker 是否收到 → 可能丢
  2. acks=1:Producer 发消息,Leader 收到即确认收到 → Leader 崩了可能丢
  3. acks=all:Producer 发消息,Leader 和 Follower 都收到消息,Leader 确认消息发送成功 → Broker 崩了可能丢
  • 当 Leader 宕机时,Kafka 会自动从 Follower 中选举新的 Leader,以保证高可用性。

Kafka 的分区 Leader 选举机制不使用 Raft 协议,在kafka 2.8之前是依赖 ZooKeeper 进行协调kafka 2.8之后即 Kafka Raft 协议
Raft协议 适用于单个集群的一致性管理,而 KRaft 是针对 Kafka 分区副本的分布式场景优化支持多分区并行选举


进一步梳理:

一、再次理解核心概念的正确关系

  1. Topic(主题)

    • Topic 是 Kafka 中消息的逻辑分类,类似于一个消息队列的名称。例如,电商系统中可能有“订单消息”“支付消息”等多个 Topic,分别存储不同类型的消息。
    • Topic 本身并不直接存储消息,而是通过“分区(Partition)”来分布式存储消息。
  2. Partition(分区)

    • 每个 Topic 可以被划分为多个 Partition(数量可配置),消息会被分散存储在这些 Partition 中。
    • Partition 是 Kafka 实现高吞吐量分布式存储的核心:
    • 多个 Partition 可以分布在不同的 Broker 上(一个 Broker 可以存放多个 Partition),实现负载均衡。
    • 消息在 Partition 中是有序存储的(按写入顺序形成日志),但不同 Partition 之间的消息无序。
  3. Broker(服务器节点)

    • Broker 是 Kafka 集群中的单个服务器节点,负责存储消息、处理生产者和消费者的请求。
    • 一个 Kafka 集群由多个 Broker 组成,Broker 之间通过 ZooKeeper 协调管理(如集群元数据、分区副本分配等)。
    • Broker 存储的是 Partition,而不是直接存储 Topic:一个 Topic 的多个 Partition 可以分布在多个 Broker 上,单个 Broker 也可以存放多个不同 Topic 的 Partition。

二、生产者与消费者的工作流程

  1. 生产者(Producer)

    • 生产者向指定的 Topic 发送消息,Kafka 会根据一定的规则(如哈希、轮询或自定义策略)将消息分配到该 Topic 的某个 Partition 中。
    • 消息一旦写入 Partition,就会被持久化(默认存盘),并生成一个唯一的偏移量(Offset)标识其在 Partition 中的位置。

    从这里可以引出kafka的高效持久化核心机制:
    0. Kafka 的 Partition 本质上是一个日志文件(Log),消息被写入时采用 “追加写入” 的方式(即只能在文件末尾顺序添加,不允许随机修改或删除

    1. kafka是存在磁盘的,向指定topic发消息,然后写入partition,(在磁盘上是顺序写入的,众所周知,在机械硬盘上,顺序写入速度可以媲美内存,固态更不用说了)将磁盘的性能发挥到了极致
    2. 由于消息只能追加在上一条消息末尾,为了适应磁盘顺序写入,引入偏移量机制,无需维护复杂的索引结构(仅通过 Offset 定位)减少了元数据开销,进一步提升写入性能
    3. 消费者通过记录 Offset,知道下次从哪个位置开始消费(例如,消费完 Offset=5 的消息后,下次从 Offset=6 开始)。
    4. 因此 Partition 内的消息通过 Offset 天然保持有序(这也是 Kafka 能保证 “分区内消息有序” 的核心)。
    5. Offset 仅在单个 Partition 内有效,不同 Partition 的 Offset 相互独立
  2. 消费者(Consumer)与消费者组(Consumer Group)

    • 消费者从 Topic 中读取消息,必须指定消费的 Partition(由 Kafka 自动分配或手动指定)。
    • 消费者组是多个消费者的集合,同一个消费者组内的消费者共同消费一个 Topic 的所有 Partition,且一个 Partition 只能被同一个消费者组内的一个消费者消费(避免重复消费)。
    • 不同消费者组可以独立消费同一个 Topic(彼此互不影响),例如“订单消息”Topic 可以被“物流系统”和“数据分析系统”两个消费者组分别消费。

三、总结关系图(简化)

Kafka 集群
├─ Broker 1
│  ├─ Topic A 的 Partition 0
│  └─ Topic B 的 Partition 1
├─ Broker 2
│  ├─ Topic A 的 Partition 1
│  └─ Topic C 的 Partition 0
└─ Broker 3└─ Topic B 的 Partition 0
  • Topic A 包含 2 个 Partition,分别在 Broker 1 和 Broker 2 上。
  • 每个 Broker 存放了不同 Topic 的 Partition。

kafka的存储机制

  1. 消息持久化

    • Kafka 的存储机制主要围绕 存在磁盘上的日志(Log) 文件来实现数据的高效存储和读取。每个 Partition 被存储为一个 日志文件,消息按照追加写(顺序)的方式存储到日志中

    通过 offest 顺序写入,顺序读取

  2. Segment分段存储

    • 每个 Partition 日志文件会进一步被分为多个 Segment。Segment 是物理上日志文件的一部分,当一个 Segment 达到预定大小或时间限制时,Kafka 会关闭这个 Segment 并开始写入下一个 Segment

    分段存储的方式使得 Kafka 在删除旧消息时不需要修改文件,只需要删除老的 Segment 文件即可

  3. 消息保留策略

    • 基于时间保留:可以配置 Kafka 将 Partition中,超过设定时间的Segment删除,例如保留 7 天的数据。
    • 基于大小保留:可以根据每个 Partition 日志文件的大小来设置消息保留,超过设定大小后,删除最早的 Segment
  4. 日志压缩

    • 永久保留最新版本的每个消息键。对于相同键的消息,Kafka 只保留最新的,删除旧的。
  5. 零拷贝

    • Kafka 在内存和网络之间的传输不经过 CPU 的数据拷贝。减少了 CPU 和内存的开销,极大提高了数据传输效率

    生产者发送消息Broker 转发消息以及消费者消费消息时都能发挥作用


Kafka的消费者策略

  1. 单独消费者模式
    • 单个消费者独占订阅的Topic分区,其他消费者无法同时消费这些分区。
  2. 消费者组模式
    • 多个消费者组成一个组,共同消费同一Topic,每个分区仅被组内一个消费者处理
    • 不同消费组可独立消费同一Topic,互不干扰。
    • 通过动态增减消费者实例灵活扩展处理能力,提升效率。

一、Kafka 确保一致性的核心机制

  1. 副本同步机制:每个分区的 Follower 副本实时从 Leader 副本同步数据,保证副本间数据一致。
  2. ISR 列表管理:仅维护与 Leader 数据同步的副本(In-Sync Replicas),非 ISR 副本不参与数据确认,避免数据不一致。
  3. Leader 唯一写入:所有读写操作由 Leader 副本处理,Follower 仅同步数据,确保同一分区的数据操作入口唯一。
  4. 选举规则约束:Leader 宕机时,仅从 ISR 中选举新 Leader,保证新 Leader 拥有最新数据,避免数据回退。

二、Kafka 确保可靠性的核心机制

  1. 持久化存储:消息按顺序写入磁盘并生成 Offset,即使 Broker 宕机,数据也不会丢失。
  2. 生产者确认机制:通过 acks 参数控制消息确认级别(如 acks=-1 要求 ISR 中多数副本确认),确保消息被安全存储。
  3. 副本冗余:多副本机制实现数据冗余,单个副本故障时,其他副本可继续提供服务。
  4. 消费者 Offset 管理:消费者通过提交 Offset 记录消费进度,支持手动提交,避免重复消费或数据丢失。
  5. 故障自动恢复:Leader 故障后自动从 ISR 选举新 Leader,Broker 故障恢复后可重新加入集群同步数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/94051.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94051.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/94051.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序连接到阿里云物联网平台

目录准备阶段阿里云配置下载mqtt.min.js文件小程序实现注意小程序配置服务器域名概述:介绍使用微信小程序连接到阿里云平台的快捷方法和完整过程。 阿里云平台建立设备,提供mqtt连接参数,小程序借助mqtt.min.js,也就是基于Github下…

2-3〔O҉S҉C҉P҉ ◈ 研记〕❘ 漏洞扫描▸AppScan(WEB扫描)

郑重声明: 本文所有安全知识与技术,仅用于探讨、研究及学习,严禁用于违反国家法律法规的非法活动。对于因不当使用相关内容造成的任何损失或法律责任,本人不承担任何责任。 如需转载,请注明出处且不得用于商业盈利。 …

LeetCode 刷题【47. 全排列 II】

47. 全排列 II 自己做 解1&#xff1a;检查重复 class Solution { public:void circle(vector<int> nums, vector<vector<int>> &res,int start){int len nums.size();if(start len - 1){ //到头了//检查重复bool is_exist fa…

Https之(一)TLS介绍及握手过程详解

文章目录简介 TLSTLS第一次握手1.Client HelloTLS第二次握手2.Server Hello3.Certificate4.Server Hello DoneTLS第三次握手5.Client Key Exchange6.Change Cipher Spec7.Encrypted Handshake MessageTLS第四次握手8.New Session Ticket9.Change Cipher Spec10.Encrypted Hands…

【WEB 】从零实现一个交互轮播图(附源码)

文章目录 一、轮播图整体功能规划二、HTML结构深度解析三、CSS样式实现细节1. 定位系统详解2. 显示/隐藏机制3. 按钮交互效果实现4. 纯CSS箭头实现5. 指示器&#xff1a;当前位置可视化 四、JavaScript逻辑深入解析1. 核心变量与DOM获取2. 图片切换函数&#xff08;核心逻辑&am…

机器学习--PCA降维

一核心部分 1解决的问题&#xff1a;应对高维数据带来的计算量大、冗余信息多、易出现过拟合等问题&#xff0c;在减少数据维度的同时尽可能保留原始数据的关键信息。2核心思想&#xff1a…

leetcode 1277. 统计全为 1 的正方形子矩阵 中等

给你一个 m * n 的矩阵&#xff0c;矩阵中的元素不是 0 就是 1&#xff0c;请你统计并返回其中完全由 1 组成的 正方形 子矩阵的个数。示例 1&#xff1a;输入&#xff1a;matrix [[0,1,1,1],[1,1,1,1],[0,1,1,1] ] 输出&#xff1a;15 解释&#xff1a; 边长为 1 的正方形有…

知识蒸馏 - 各类概率分布

知识蒸馏 - 各类概率分布 flyfish一、离散概率分布 离散分布描述的是取值为离散值&#xff08;如0,1,2,…&#xff09;的随机变量的概率规律&#xff0c;通常用概率质量函数&#xff08;PMF&#xff09; 表示某一取值的概率。 1. 伯努利分布&#xff08;Bernoulli Distribution…

软件测试-Selenium学习笔记

""" 目标&#xff1a; driver.find_element() 需求&#xff1a; 1. 使用driver.find_element()方法 2. 输入用户名&#xff1a;admin 3. 输入密码&#xff1a;123456 """ # 导包 from selenium import webdriver from time import …

知微传感3D相机上位机DkamViewer使用:给相机升级固件

写在前面 本人从事机器视觉细分的3D相机行业。编写此系列文章主要目的有&#xff1a; 1、便利他人应用相机&#xff0c;本系列文章包含公司所出售相机的SDK的使用例程及详细注释&#xff1b;2、促进行业发展及交流。 知微传感Dkam系列3D相机可以应用于定位分拣、焊接焊缝提取、…

CMake进阶: CMake Modules---简化CMake配置的利器

目录 1.简介 2.为什么需要 CMake Modules&#xff1f; 3.内置模块&#xff1a;开箱即用的工具 3.1.依赖查找模块&#xff08;FindXXX.cmake&#xff09; 3.2.功能检测模块&#xff08;CheckXXX.cmake&#xff09; 3.3.通用工具模块&#xff08;如 FetchContent.cmake、CT…

【Docker】Ubuntu上安装Docker(网络版)

【Docker】Ubuntu上安装Docker注意&#xff1a;一、环境准备1. 系统要求2. 卸载旧版本二、安装步骤1.配置仓库源2.安装 Docker引擎3.验证安装情况三、解决报错1、检查网络连接2、检查Docker服务状态3、换源4.重载生效、重启服务、查看是否配置成功5.验证解决情况四、权限与配置…

Socket 编程 TCP

TCP 网络程序 和刚才 UDP 类似. 实现一个简单的英译汉的功能。TCP是面向字节流的可靠传输&#xff0c;如同前文的管道流&#xff0c;只要是流&#xff0c;它的操作就是文件的写出与读入。TCP socket API 详解下面介绍程序中用到的 socket API,这些函数都在 sys/socket.h 中。so…

使用AWS S3 + Lambda + MediaConvert 实现上传视频文件并自动转码

前言 最近团队在做短视频平台的技术调研&#xff0c;其中有一个环节便是音视频开发&#xff0c;即对用户上传的视频进行自适应转码。自适应的原理其实就是预先将视频转换为几个常用的分辨率&#xff0c;app端根据用户手机分辨率拉取相应分辨率的视频。 目前尝试了两种方案&…

QT之QWaitCondition降低cpu占用率,从忙等待到高效同步

在多线程编程中&#xff0c;线程间的同步是一个核心问题。在处理线程等待时&#xff0c;经常会写出高CPU占用率的代码&#xff0c;其中最典型的就是使用忙等待&#xff08;busy waiting&#xff09;。本文将详细介绍如何使用Qt框架中的QWaitCondition类来优雅地解决这一问题&am…

pcl求平面点云的边界凸包点

基本流程1&#xff0c;读入点云&#xff0c;并去除无效点2&#xff0c;拟合平面3&#xff0c;去除离平面距离较远的点4&#xff0c;对点云进行平面投影5&#xff0c;进行convex_hull运算初学者&#xff0c;暂时不知道能用来干嘛。练手还是非常不错的&#xff01;#define _CRT_S…

Windows系统上使用GIT

首先破除一下畏惧心理&#xff1a;在Windows上使用git和在linux系统中的使用方法是一样的&#xff0c;只是安装方式没那么便捷&#xff0c;毕竟linux中安装git只需要一行命令 GIT下载地址 如果你的电脑的CPU是64位的&#xff0c;就点击&#xff1a; Git-2.50.1-64-bit.exe 如果…

《设计模式之禅》笔记摘录 - 17.模板方法模式

模板方法模式的定义模板方法模式(Template Method Pattern)是如此简单&#xff0c;以致让你感觉你已经能够掌握其精髓了。其定义如下&#xff1a;Define the skeleton of an algorithm in an operation, deferring some steps to subclasses.Template Method lets subclasses r…

SpreadJS 协同服务器 MongoDB 数据库适配支持

为了支持 SpreadJS 协同编辑场景&#xff0c;协同服务器需要持久化存储文档、操作、快照及里程碑数据。本文介绍了 MongoDB 数据库适配器的实现方法&#xff0c;包括集合初始化、适配器接口实现以及里程碑存储支持。 一、MongoDB 集合初始化 协同编辑服务需要以下集合&#x…

Ubuntu 主机名:精通配置与管理

主机名&#xff08;hostname&#xff09;是Linux系统中用于标识网络上特定设备的名称&#xff0c;它在网络通信、服务配置&#xff08;如 Kubernetes 集群、数据库&#xff09;以及日志记录中扮演着至关重要的角色。对于初学者来说&#xff0c;配置主机名似乎很简单&#xff0c…