【八股消消乐】消息队列优化—消息有序

在这里插入图片描述

😊你好,我是小航,一个正在变秃、变强的文艺倾年。
🔔本专栏《八股消消乐》旨在记录个人所背的八股文,包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点,期待与你一同探索、学习、进步,一起卷起来叭!

目录

  • 题目
  • 答案
    • Kafka 消息分区
    • 有序消息
    • 跨topic的有序消息
    • 简历优化
      • 单分区
      • 异步消费
      • 多分区
        • 数据不均匀
          • 槽与槽分配
          • 一致性哈希
        • 消息失序

题目

💬技术栈:RocketMQ、Kafka、RabbitMQ

🔍简历内容:熟悉Kafka消息分区。为解决Kafka线上消息积压、broker性能抖动问题,针对业务内有序为topic实现了多分区。参考Redis槽与槽分配机制解决了数据不均匀问题。针对分区扩容采用了停顿方案解决消息失序问题。

🚩面试问:你觉得在多分区方案里面,如果某个分区消息积压了就启用异步消费,这种解决思路你觉得怎么样?


在这里插入图片描述

💡建议暂停思考10s,你有答案了嘛?如果你有不同题解,欢迎评论区留言、打卡。


答案

Kafka 消息分区

在 Kafka 中,消息是以分区为单位进行存储的。每个 topic 都可以被划分为一个或多个分区,每个分区都是一个 有序、不可变 的消息日志。Kafka 使用 WAL (write-ahead-log)日志来存储消息。每个分区都有一个对应的日志文件,新的消息会被追加到文件的末尾,而已经加入日志里的消息,就不会再被修改了。

在这里插入图片描述

每个消息在分区日志里都有一个唯一的偏移量(offset),用来标识消息在分区里的位置。 Kafka 保证同一分区内的消息顺序,但不保证不同分区之间的顺序。而 Kafka 本身暴露了对应的接口,也就是说你可以显式地指定消息要发送到哪个分区,也可以显式地指定消费哪个分区的数据。

有序消息

有序消息:消费者消费某个 topic 消息的顺序,和生产者生产消息的顺序一模一样。

生产者生产消息的顺序,不是指你创建出来消息那个实例的先后顺序,而是指broker收到的顺序。
在这里插入图片描述

跨topic的有序消息

问题:保证不同topic之间消息是有序的。比如说 msg1 先发送到了 topic_a 上, msg2 被发送到了 topic_b 上。但是在业务层面上,要求 msg1 一定要先于 msg2 消费

解决方案:引入一个协调者,这个协调者负责把消息重组为有序消息。比如说,如果 msg2 先到了,但是 msg1 还没出来,那么这个协调者要有办法让 msg2 的消费者 B 停下来,暂时不消费 msg2。而在 msg1 来了之后,唤醒消费者 A 消费 msg1,并且在消费完 msg1 之后要再唤醒消费者 B 处理 msg2。

简历优化

前置准备:

  • 在什么业务场景下,你需要用到有序消息?
  • 你是如何解决有序消息这个问题的?用的是哪种方案?
  • 如果你用的是单分区解决方案,那么有没有消息积压问题?如果有,你是怎么解决的?
  • 如果你用的是多分区解决方案,那么有没有分区负载不均衡的问题?如果有,你是怎么解决的?

单分区

解决方案:为了保证消息有序,让特定的 topic 只有一个分区。这样所有的消息都发到同一个分区上,那么自然就是有序的。

存在的问题: 性能差、消息积压。

  • 生产端:所有的消息都在一个分区上,也同时意味着所有的消息都发送到了同一个broker上,这个服务器很可能撑不住压力;
  • 消费端:只有一个分区,那么就只能有一个消费者消费,很容易出现消息积压的问题。

在这里插入图片描述

全局有序:没什么优化手段,只能是换用更加强大的机器。
业务内有序:比如说在下单的场景下,会产生创建订单消息和完成支付消息。业务上只会要求同一个订单的创建订单消息应该优先于完成支付消息,但是不会要求订单 A 的创建消息需要先于订单 B 的支付消息。这种解决方案参考下面的异步消费、多分区方案。

异步消费

问题:单分区方案中,由于只有一个消费者,容易造成消息积压。

解决方案:保证同一个业务内的顺序。当消费者从队列取出来消息之后,把同一个业务的消息丢到同一个队列里。

在这里插入图片描述
消费者线程从 Kafka 里获取消息,然后转发到内存队列里面。在转发的时候,要把同一个业务的消息转发到同一个队列里面。一般来说可以根据业务特征字段计算一个哈希值,比如说直接使用业务 id 作为哈希值。利用这个哈希值除以工作线程数量,然后取余数,得到对应的内存队列

存在的问题:可能存在消息未消费。消费线程取出来了,转发到队列之后,工作线程还没来得及处理,消费者整体就宕机了,那么这些消息就存在丢失的可能。

多分区

将上面方案的内存队列换成了多个分区。原本同一个业务的消息发送到同一个分区。

保证同一个业务的消息必然发送到同一个分区:生产者在发送消息的时候,根据业务特征,比如说业务 ID 计算出目标分区,在发送的时候显式地指定分区就可以了。

在这里插入图片描述

引发的问题:数据不均匀、增加分区可能导致消息失序。

数据不均匀

问题:数据不均匀一般是业务造成的。在我们的方案里面,分区是根据业务特征来选择的,那么自然有一些分区有很多数据,有一些分区数据很少。比如说万一我们不小心把热点用户的消息都发到了同一个分区里面,那么这个分区的 QPS 就会很高,消费者也不一定来得及消费,就可能引起消息积压。

在这里插入图片描述

解决方案:Redis 中槽和槽分配的机制,又或者说一致性哈希算法。

槽与槽分配

借鉴 Redis 的槽与槽分配方案。不过 Redis 使用了 16384 个槽,一般的业务用不上那么多槽,所以可以考虑用 1024 个槽根据业务的特征来计算一个哈希值,再除以 1024 取余就可以得到所在的槽。再根据不同槽的数据多少,合理地把槽分配到不同的分区。最好把槽和分区的绑定关系做成动态的,也就是说我可以随时调整槽到分区的映射关系,保证所有的分区负载都是均匀的。

在这里插入图片描述

动态调整槽与分区的绑定:借助于配置中心来完成。比如说最开始你把槽 1 绑定到分区 2 上,后面在运行的时候你发现分区 2 数据太多,就把槽 1 重新绑定到了分区 3 上

一致性哈希

使用一致性哈希算法来筛选分区。首先要根据数据分布的整体情况,把分区分布在哈希环上,确保每一个分区上的数据分布大体上是均匀的。如果一部分哈希值上数据较多,就多插入几个分区节点。然后根据业务特征计算一个哈希值,从哈希环上找到对应的分区

在这里插入图片描述

消息失序

场景:如果中间有增加新的分区,那么就可能引起消息失序。比如说最开始 id 为 3 的订单消息 msg1 发到分区 0 上,但是这时候很不幸分区 0 上积攒了很多消息,所以 msg1 迟迟得不到消费。紧接着我们扩容,增加了一个新的分区。如果这时候来了一个消息 msg2,那么它会被转发到分区 3 上。分区 3 上面没有积攒什么数据,所以消费者 3 直接就消费了这个消息。本来 msg1 应该先于 msg2 被消费。而增加分区之后 msg2 反而被先消费了。

解决方案:对于新加入的分区,可以暂停消费一段时间。如果我们估算 msg1 会在一分钟内被消费,那么新加入的分区的消费者可以在三分钟后再开始消费。那么大概率 msg1 就会先于 msg2 消费

不过这种等待的解决方式并不能解决根本问题,只能说是很大程度上缓解了问题。但是本身增加分区也是一个很不常见的操作,再叠加消息失序的概率也很低,所以我们也可以通过监控发现这种失序场景,然后再手工修复一下就可以了

简历总结:

最开始我进公司的时候就遇到了一个 Kafka 的线上故障。我司有一个业务需要用到有序消息,所以最开始的设计就是对应的 topic 只有一个分区,从而保证了消息有序。

可是随着业务增长,一个分区很快就遇到了性能瓶颈。只有一个分区,也就意味着只有一个消费者,所以在业务增长之后,就开始出现了消息积压。另外一方面,这个分区所在的broker的负载也明显比其他服务器要大,偶尔也会有一些性能抖动的问题。

后来我仔细看了我们的业务,实际上,我们的业务要求的不是全局有序,而是业务内有序。

换句话来说,不一定非得用一个分区,而是可以考虑使用多个分区。所以我就给这个 topic 增加了几个分区,同时也增加了消费者。优化完之后,到目前为止,还没有出现过消息积压的问题。

当然,为了避免在单分区增加到多分区的时候,出现消息失序的问题,我用了一个很简单的方案,就是对应的消费者在启动之后,并没有立刻消费,而是停顿了三分钟,从而避免了潜在的消息失序问题。


往期精彩专栏内容,欢迎订阅:

🔗【八股消消乐】20250624:消息队列优化—延迟消息
🔗【八股消消乐】20250623:消息队列优化—系统架构设计
🔗【八股消消乐】20250622:Elasticsearch查询优化
🔗【八股消消乐】20250620:Elasticsearch优化—检索Labubu
🔗【八股消消乐】20250619:构建微服务架构体系—保证服务高可用
🔗【八股消消乐】20250615:构建微服务架构体系—链路超时控制
🔗【八股消消乐】20250614:构建微服务架构体系—实现制作库与线上库分离
🔗【八股消消乐】20250612:构建微服务架构体系—限流算法优化
🔗【八股消消乐】20250611:构建微服务架构体系—降级策略全总结
🔗【八股消消乐】20250610:构建微服务架构体系—熔断恢复抖动优化
🔗【八股消消乐】20250609:构建微服务架构体系—负载均衡算法如何优化
🔗【八股消消乐】20250608:构建微服务架构体系—服务注册与发现
🔗【八股消消乐】20250607:MySQL存储引擎InnoDB知识点汇总
🔗【八股消消乐】20250606:MySQL参数优化大汇总
🔗【八股消消乐】20250605:端午节产生的消费数据,如何分表分库?
🔗【八股消消乐】20250604:如何解决SQL线上死锁事故
🔗【八股消消乐】20250603:索引失效与优化方法总结
🔗【八股消消乐】20250512:慢SQL优化手段总结
🔗【八股消消乐】20250511:项目中如何排查内存持续上升问题
🔗【八股消消乐】20250510:项目中如何优化JVM内存分配?
🔗【八股消消乐】20250509:你在项目中如何优化垃圾回收机制?
🔗【八股消消乐】20250508:Java编译优化技术在项目中的应用
🔗【八股消消乐】20250507:你了解JVM内存模型吗?
🔗【八股消消乐】20250506:你是如何设置线程池大小?
🔗【八股消消乐】20250430:十分钟带背Duubo中大厂经典面试题
🔗【八股消消乐】20250429:你是如何在项目场景中选取最优并发容器?
🔗【八股消消乐】20250428:你是项目中如何优化多线程上下文切换?
🔗【八股消消乐】20250427:发送请求有遇到服务不可用吗?如何解决?

📌 [ 笔者 ]   文艺倾年
📃 [ 更新 ]   2025.6.25
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!

在这里插入图片描述

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

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

相关文章

2D写实交互数字人如何重塑服务体验?

在数字化浪潮席卷全球的当下,人机交互模式正经历着前所未有的变革。从早期的文本命令行界面,到图形用户界面(GUI)的普及,再到如今语音交互、手势识别等多模态交互技术的兴起,我们与机器之间的沟通方式愈发自…

CI/CD GitHub Actions配置流程

腾讯云服务器宝塔FinalShellgithup 1.在云服务器上创建SSH秘钥对,下载秘钥到本地 2.在服务器中绑定秘钥对(绑定后,服务器不能将不允许密码登录)绑定前先关机服务器,绑定后再开启服务器 3.FinalShell改为公钥登录&am…

液态交互效果网页开发--源自鸿蒙5以及iOS26的灵感

首先先来看看最终展示效果 当鼠标靠近“开始探索”的按钮的时候,按钮放大并有微弱光效 鼠标靠近之前会给视窗添加一层接近背景的朦胧感,当鼠标放在视窗上朦胧感消失 技术不复杂,这个网页主要是使用了以下关键技术: HTML5 语义化标…

PYTHON从入门到实践9-类和实例

# 【1】面向对象编程 class Student(object):# 可以帮属性值绑定到对象上,self相当于JAVA的thisdef __init__(self, name, age):self.name nameself.age agedef speak(self):print(self.name, 说:老师好)if __name__ __main__:new_student1 Student(…

matplotlib 绘制极坐标图

1、功能介绍: 使用了 matplotlib 库来创建一个极坐标图 2、代码部分: import matplotlib.pyplot as plt import numpy as np# 设置中文字体 plt.rcParams[font.sans-serif] [SimHei] # 选择黑体字体,支持中文 plt.rcParams[axes.unicode…

Dask心得与笔记【2】

文章目录 计算参考文献 计算 数组切片如下 import numpy as np import dask.array as dadata np.arange(1000).reshape(10, 100) a da.from_array(data, chunks(5, 20)) print(a[:,0:3])切片结果是前3列 dask.array<getitem, shape(10, 3), dtypeint64, chunksize(5, 3…

数据采集合规安全是品牌控价基石

在品牌控价与数据分析工作中&#xff0c;数据采集是不可或缺的前置环节。当前主流的数据采集方式为爬虫采集&#xff0c;这种依托机器自动化操作的模式&#xff0c;取代了传统人工逐一浏览、复制数据的繁琐流程&#xff0c;大幅提升了效率。采集后的原始数据&#xff0c;会由系…

llm推理赋能action policy的探索

兄弟&#xff0c;你这个问题非常到位&#xff0c;咱分两个问题详细讲透&#xff1a; &#x1f680; (1) HybridVLA怎么引入更好的推理能力赋能Diffusion Action&#xff1f; HybridVLA 目前设计的亮点&#xff1a; Diffusion Token 与 LLM 自回归结合 但推理能力没有被显式结…

spring04-管理bean(创建、注入):基于注解

一、什么是注解&#xff1f; &#xff08;1&#xff09;注解的定义 注解&#xff08;Annotation&#xff09;是 Java 代码中的一种特殊标记&#xff0c;用于在程序运行或编译时提供元信息。 格式&#xff1a; 注解名(属性名属性值, 属性名属性值...)&#xff08;2&#xff…

docker安装elasticsearch和kibana

elasticsearch版本和kibana版本需保持一致。这里我使用的都是8.18.2 安装elasticsearch docker-compose.yml networks:es-net: external: true services:elasticsearch:container_name: es01deploy:resources:limits:cpus: 0memory: 0environment:- discovery.typesingle-no…

Python爬虫实战:研究sanitize库相关技术

1. 引言 1.1 研究背景与意义 在当今数字化时代,互联网已成为人们获取信息、交流互动的重要平台。随着 Web 2.0 技术的发展,用户生成内容 (UGC)、社交媒体嵌入、第三方插件等功能极大丰富了网页的内容和交互性,但也带来了严峻的安全挑战。根据 Web 应用安全联盟 (WAS) 的统…

c++ 学习(二、结构体)

目录 一、结构体与const 二、结构体与class的区别 参考链接&#xff1a;69 结构体-结构体中const使用场景_哔哩哔哩_bilibili 一、结构体与const 调用函数的时候&#xff0c;希望这个结构体是可读而不可写的时候&#xff0c;传指针&#xff0c;使用const修饰&#xff0c;方式…

机器学习开篇:算法分类与开发流程

种一棵树最好的时间是十年前&#xff0c;其次是现在。 一、机器学习算法分类 机器学习&#xff08;ML&#xff0c;Meachine Learning&#xff09;是人工智能的核心领域&#xff0c;让计算机从数据中学习规律并做出预测&#xff0c;本文简单介绍机器学习的算法分类和开发流程。…

使用pyflink编写demo并将任务提交到yarn集群

目录 背景 一、pyflink安装 二、编写demo程序 三、提交yarn前准备 四、提交任务 五、踩坑记录 1、提交任务时客户端出现语法错误 2、提交任务时客户端出现lzma包找不到 3、提交任务时客户端出现“org.apache.flink.streaming.api.utils.PythonTypeUtils.getCollectionIn…

Vue 3 最基础核心知识详解

Vue3作为现代前端主流框架&#xff0c;是前后端开发者都应当掌握的核心技能。本篇文章将带你了解vue3的基础核心知识&#xff0c;适合学习与复习 一、Vue 3 应用创建 1.1 创建Vue应用的基本步骤 // main.js import { createApp } from vue // 1. 导入createApp函数 import …

Bootstrap 5学习教程,从入门到精通,Bootstrap 5 Flex 布局语法知识点及案例(27)

Bootstrap 5 Flex 布局语法知识点及案例 Bootstrap 5 提供了强大的 Flexbox 工具集&#xff0c;让布局变得更加简单灵活。以下是 Bootstrap 5 Flex 布局的完整知识点和详细案例代码。 一、Flex 布局基础语法 1. 启用 Flex 布局 <div class"d-flex">我是一个…

HarmonyOS 5智能单词应用开发:记忆卡(附:源码

一、应用概述与核心价值 在语言学习过程中&#xff0c;单词记忆是基础也是难点。本文介绍的智能单词记忆卡应用通过创新的交互设计和科学的学习模式&#xff0c;帮助用户高效记忆单词。应用采用ArkUI框架开发&#xff0c;主要特点包括&#xff1a; 双模式学习系统&#xff1a…

LeetCode--38.外观数列

前言&#xff1a;之前我不是说&#xff0c;我后续可能会讲一下递归吗&#xff0c;现在它来了&#xff0c;这道题会用到回溯的方法&#xff0c;并且比较纯粹哦 解题思路&#xff1a; 1.获取信息&#xff1a;&#xff08;下面这些信息差不多是力扣上面的题目信息了&#xff0c;所…

服务器的安装与安全设置

1&#xff1a;安装操作系统 1、创建虚拟机Win49&#xff08;49为序号&#xff09;&#xff0c;并安装Windows Server 2019操作系统 参考配置&#xff1a;安装系统的分区大小为20GB&#xff0c;其余分区暂不划分&#xff0c; 文件系统格式为NTFS&#…

Sensodrive SensoJoint机器人力控关节模组抗振动+Sensodrive力反馈系统精准对接

Sensodrive成立于2003年&#xff0c;起源于德国航空航天中心&#xff08;DLR&#xff09;的LBR项目。公司由一批传感器技术专家创立&#xff0c;专注于高精度工业扭矩传感器的研发。凭借二十余年的技术积累&#xff0c;Sensodrive将DLR轻型机器人扭矩技术引入工业领域&#xff…