当前位置: 首页 > news >正文

五角钱的程序员 | Kafka 是什么?

本文来源公众号“五角钱的程序员”,仅用于学术分享,侵权删,干货满满。

原文链接:Kafka 是什么?

你是一个程序员,假设你维护了两个服务 A 和 B。B 服务每秒只能处理 100 个消息,但 A 服务却每秒发出 200 个消息,B 服务哪里顶得住,分分钟被压垮。那么问题就来了,有没有办法让 B 在不被压垮的同时,还能处理掉 A 的消息?当然有,没有什么是加一层中间层不能解决的,如果有,那就再加一层。这次我们要加的中间层是 消息队列 Kafka

Kafka

1 什么是消息队列

为了保护 B 服务,我们很容易想到可以在 B 服务的内存中加入一个队列

消息队列在B进程里

说白了,它其实是个链表,链表的每个节点就是一个消息。每个节点有一个序号,我们叫它 Offset,记录消息的位置。B 服务依据自己的处理能力,消费链表里的消息。能处理多少是多少,不断更新已处理 Offset 的值。

Offset是什么

但这有个问题,来不及处理的消息会堆积在内存里,如果 B 服务更新重启,这些消息就都丢了。这个好解决,将队列挪出来,变成一个单独的进程。就算 B 服务重启,也不会影响到了队列里的消息。

消息队列单独一个进程

这样一个简陋的队列进程,其实就是所谓的消息队列。而像 A 服务这样负责发数据到消息队列的角色,就是生产者,像 B 服务这样处理消息的角色,就是消费者

生产者和消费者

但这个消息队列属实过于简陋,像什么高性能,高扩展性,高可用,它是一个都不沾。我们来看下怎么优化它。

2 高性能

B 服务由于性能较差,消息队列里会不断堆积数据,为了提升性能,我们可以扩展更多的消费者, 这样消费速度就上去了,相对的我们就可以增加更多生产者,提升消息队列的吞吐量。

增加生产者和消费者

随着生产者和消费者都变多,我们会发现它们会同时争抢同一个消息队列,抢不到的一方就得等待,这不纯纯浪费时间吗!有解决方案吗?有!首先是对消息进行分类,每一类是一个 topic,然后根据 topic 新增队列的数量,生产者将数据按 topic 投递到不同的队列中,消费者则根据需要订阅不同的 topic。这就大大降低了 topic 队列的压力。

多个topic

但单个 topic 的消息还是可能过多,我们可以将单个队列,拆成好几段,每段就是一个 partition分区,每个消费者负责一个 partition。这就大大降低了争抢,提升了消息队列的性能。

partition

3 高扩展性

随着 partition 变多,如果 partition 都在同一台机器上的话,就会导致单机 cpu 和内存过高,影响整体系统性能。

于是我们可以申请更多的机器,将 partition 分散部署在多台机器上,这每一台机器,就代表一个 broker。我们可以通过增加 broker 缓解机器 cpu 过高带来的性能问题。

broker

4 高可用

到这里,其实还有个问题,如果其中一个 partition 所在的 broker 挂了,那 broker 里所有 partition 的消息就都没了。这高可用还从何谈起?有解决方案吗?有,连你喜欢的女生都知道手机里多聊几个沸羊羊,你却不知道要给 partition 加备胎吗?我们可以给 partition 多加几个副本,也就是 replicas,将它们分为 Leader 和 Follower。Leader 负责应付生产者和消费者的读写请求,而 Follower 只管同步 Leader 的消息。

replicas

将 Leader 和 Follower 分散到不同的 broker 上,这样 Leader 所在的 broker 挂了,也不会影响到 Follower 所在的 broker, 并且还能从 Follower 中选举出一个新的 Leader partition 顶上。这样就保证了消息队列的高可用。

高可用

5 持久化和过期策略

刚刚提到的是几个 broker 挂掉的情况,那搞大点,假设所有 broker 都挂了,那岂不是数据全丢了?为了解决这个问题,我们不能光把数据放内存里,还要持久化到磁盘中,这样哪怕全部 broker 都挂了,数据也不会全丢,重启服务后,也能从磁盘里读出数据,继续工作。

持久化

但问题又来了,磁盘总是有限的,这一直往里写数据迟早有一天得炸。所以我们还可以给数据加上保留策略,也就是所谓的 retention policy,比如磁盘数据超过一定大小或消息放置超过一定时间就会被清理掉。

6 consumer group

到这里,这个消息队列好像就挺完美了。但其实还有个问题,按现在的消费方式,每次新增的消费者只能跟着最新的消费 Offset 接着消费。如果我想让新增的消费者从某个 Offset 开始消费呢?听起来这个需求很刁钻?我举个例子你就明白了。

哪怕 B 服务有多个实例,但本质上,它只有一个消费业务方,新增实例一般也是接着之前的 offset 继续消费。假设现在来了个新的业务方,C 服务,它想从头开始消费消息队列里的数据,这时候就不能跟在 B 服务的 offset 后边继续消费了。

所以我们还可以给消息队列加入消费者组(consumer group)的概念,B 和 C 服务各自是一个独立的消费者组,不同消费者组维护自己的消费进度,互不打搅。

消费者组互相独立

7 ZooKeeper

相信你也发现了,组件太多了,而且每个组件都有自己的数据和状态,所以还需要有个组件去统一维护这些组件的状态信息,于是我们引入 ZooKeeper 组件。它会定期和 broker 通信,获取 整个 kafka 集群的状态,以此判断 某些 broker 是不是跪了,某些消费组消费到哪了。

图片

加入ZooKeeper

Kafka 是什么

好了,到这里,当初那个简陋的消息队列,就成了一个高性能,高扩展性,高可用,支持持久化的超强消息队列,没错,它就是我们常说的消息队列 Kafka,上面涉及到各种概念,比如 partition 和 broker 什么的,都出自它。

图片

Kafka是什么

kafka 的应用场景

消息队列是架构中最常见的中间件之一,使用场景之多,堪称万金油!比如上游流量忽高忽低,想要削峰填谷,提升 cpu/gpu 利用率,用它。又比如系统过大,消息流向盘根错节,想要拆解组件,降低系统耦合,还是用它。再比如秒杀活动,请求激增,想要保护服务的同时又尽量不影响用户,还得用它。当然,凡事无绝对,方案还得根据实际情况来定,做架构做到最后,都是在做折中

图片

Kafka的应用场景

总结

  • kafka 是消息队列,像消息队列投递消息的是生产者,消费消息的是消费者。增加生产者和消费者的实例个数可以提升系统吞吐。多个消费者可以组成一个消费者组,不同消费者组维护自己的消费进度,互不打搅。

  • kafka 将消息分为多个 topic,每个 topic 内部拆分为多个 partition,每个 partition 又有自己的副本,不同的 partition 会分布在不同的 broker 上,提升性能的同时,还增加了系统可用性和可扩展性。

THE END !

文章结束,感谢阅读。您的点赞,收藏,评论是我继续更新的动力。大家有推荐的公众号可以评论区留言,共同学习,一起进步。

相关文章:

五角钱的程序员 | Kafka 是什么?

本文来源公众号“五角钱的程序员”,仅用于学术分享,侵权删,干货满满。 原文链接:Kafka 是什么? 你是一个程序员,假设你维护了两个服务 A 和 B。B 服务每秒只能处理 100 个消息,但 A 服务却每秒…...

C++中合成的默认构造函数的访问权限

问题 我们知道,在C中,如果没有为一个类显式定义构造函数,那么编译器会为我们隐式地定义一个默认构造函数。那么,你有没有想过,这个隐式定义的默认构造函数(合成的默认构造函数)的访问权限是什么…...

【前端】桌面版docker并部署前端项目

环境 win10专业版 2004 , 需科学 官网下载安装包并安装4.29.0版本 终端输入 wsl --installdocker桌面版和模拟器只能选一个,不然一直转圈圈 镜像配置加速,在settings—>docker engine下 {"builder": {"gc": {"defaultKee…...

发布GPT-5的方式可能会与以往不同;开源vocode使用 AI 自动拨打电话;开源gpt智能对话客服工具;AI自动写提示词

✨ 1: vocode 用AI通过声音与用户进行实时交流 Vocode是一个旨在帮助开发者快速构建基于声音的大型语言模型(LLM)应用程序的开源库。简单来说,如果你想要开发一个能够通过声音与用户进行实时交流的应用,比如电话机器人、语音助手…...

Linux 作业管理 (bg, fg, jobs, kill)

bg 和 fg 是用来管理作业(在 Unix/Linux 命令行下运行的进程)的命令。 1. bg 命令 bg 命令用于将作业(job)放到后台运行。当你在终端中运行一个命令或程序时,它会占用当前终端的控制,如果你想让这个任务在…...

springboot Redis 支持星号(*) 包括注解@Cache

通过自定义CacheManager Bean来实现 bean Autowiredprivate RedisConnectionFactory redisConnectionFactory;/*** 管理缓存** return*///缓存管理器PrimaryBeanOverridepublic CacheManager cacheManager() {// 使用自定义的缓存配置初始化一个cacheManagerreturn new Custom…...

2023.5.12 第43周周报

学习时间:2023.5.5-2023.5.12 学习内容: 1、answer question: img: 看到有论文说应该让图像和文本的潜在嵌入具有相似和合理的数值范围【-2,2】 调试发现模型的文本图像的潜在嵌入虽然符合,但相差较大。 在将文本和…...

JavaEE 多线程详细讲解(2)

1.线程不安全分析 (1)线程不安全的主要原因就是,系统的抢占式执行,对于内核设计者来说,这是非常方便的一个执行方式,但是这却却导致线程不安全的问题,也有不抢占执行的系统,但是这种…...

Flask-HTTP请求、响应、上下文、进阶实验

本节主要目录如下: 一、请求响应循环 二、HTTP请求 2.1、请求报文 2.2、Request对象 2.3、在Flask中处理请求 2.4、请求钩子 三、HTTP响应 3.1、响应报文 3.2、在Flask中生成响应 3.3、响应格式 3.4、Cookie 3.5、session:安全的Cookie 四、…...

springboot 设置response和request的默认格式 驼峰或者SNAKE_CASE

springboot 设置response和request的默认格式 驼峰或者SNAKE_CASE。 我们使用默认配置的情况下,response和request是由jackson jason序列化和解析的,因此,我们只需要配置好jackson json的默认格式就可以。 要设置 jackson json默认的更多格式…...

VR全景技术在养老院的应用优势浅析

随着时代的快速发展,人口老龄化越来越严重,如何利用VR技术提升养老服务的质量,成为了社会各界关注的焦点。为养老院拍摄制作VR全景,不仅能够为养老院的老人子女们跨越空间限制,实现与家人的情感连接,还可以…...

[Spring Cloud] (6)gateway整体加解密

文章目录 简述整体效果后端增加配置nacos增加配置GlobalConfig 添加请求整体解密拦截器DecryptionFilter添加响应整体解密拦截器EncryptionFilter 前端请求拦截器添加整体加密逻辑请求头中添加sessionId 响应拦截器添加整体解密逻辑 简述 本文网关gateway,微服务&a…...

RUST编程语言入门基础2024

庄晓立,2024年3月。 Rust简介 A language empowering everyone to build reliable and efficient software. Rust编程语言赋能所有人开发高可靠且高性能的软件。 性能 Rust is blazingly fast and memory-efficient: with no runtime or garbage collector, it can…...

Linux进程控制——Linux进程终止

前言:前面了解完前面的Linux进程基础概念后,我们算是解决了Linux进程中的一大麻烦,现在我们准备更深入的了解Linux进程——Linux进程控制! 我们主要介绍的Linux进程控制内容包括:进程终止,进程等待与替换&a…...

利用IP地址查询解决被“薅羊毛”的方法

在互联网时代,随着各种网络诈骗手段的不断更新和演变,“薅羊毛”成为了一种常见的网络犯罪行为。其中,利用查询IP地址进行欺诈活动已经成为一种普遍的手段。当个人或组织的IP地址被不法分子查询后,可能会面临虚假注册、盗取个人信…...

Tomcat7+ 弱口令 后台getshell漏洞

1 漏洞背景 Tomcat 是一个流行的开源Web应用服务器,用于部署和运行Java Web应用程序。Tomcat 7 版本中存在一个安全隐患,即默认的管理员密码可能较弱或者未被修改,攻击者可以利用这一漏洞登录到Tomcat的管理后台,并上传恶意的WAR…...

香港虚拟主机哪里可以试用?用于企业建站的

香港虚拟主机适合个人、企业建站,包括外贸企业网站、个人博客网站、中小企业官网等,那么作为新手不知道哪家香港虚拟主机好用的时候,该如何找到可以试用的香港虚拟主机呢? 香港虚拟主机也称作香港空间、香港虚拟空间,…...

C# 集合(四) —— Set类

总目录 C# 语法总目录 集合四 Set 1. Set 1. Set 有 HashSet 和 SortedSet, 它们都不包含重复元素忽略添加重复值的请求无法根据位置访问元素使用Contains方法均使用散列查找,所以速度快 SortedSet 按照一定顺序保存元素,使用红黑树实现&a…...

C#实现多线程的几种方式

前言 多线程是C#中一个重要的概念,多线程指的是在同一进程中同时运行多个线程的机制。多线程适用于需要提高系统并发性、吞吐量和响应速度的场景,可以充分利用多核处理器和系统资源,提高应用程序的性能和效率。 多线程常用场景 CPU 密集型任务…...

C语言—控制语句

控制语句就是用来实现对流程的选择、循环、转向和返回等控制行为。 分支语句 if语句 基本结构 if(表达式) { 语句块1; } else { 语句块2; } 执行顺序: 如果表达式判断成立(即表达式为真),则执行语句块…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...