首页 > 其他分享 >分布式进阶(五)——分布式框架之高性能:消息有序性

分布式进阶(五)——分布式框架之高性能:消息有序性

时间:2024-04-05 09:02:11浏览次数:26  
标签:顺序 码哥 进阶 源码 消息 有序性 多线程 分布式

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

 

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

 

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

 

一、何谓有序性

消息有序性,就是说进入消息队列的消息都是有顺序的,消息应该按照FIFO的顺序被消费。这对消费者端的处理逻辑是有要求的,比如消息按照消息A、消息B、消息C的顺序先后进入队列,那么消费者程序的处理逻辑也应该是先执行消息A、再执行消息B、最后执行消息C。

我们在《分布式理论之高性能:读写分离》中介绍过MySQL的复制原理:整个复制过程实际上就是 Slave节点 从Master节点获取binlog日志,然后再顺序执行日志中所记录的各种操作。如果Slave中的SQL线程在消费数据时不保证顺序,那原来的[增加、修改、删除]可能就变成了[删除、修改、增加],就会全部乱套。

本章,我们依旧以RabbitMQ和Kafka为例,看下他俩是如何保证消息的有序性的。

二、RabbitMQ

在RabbitMQ中,当多个消费者对同一个queue进行消费时,是不能保证消息的有序执行的。比如消息按照消息A、消息B、消息C的顺序先后进入一个队列,但是当有多个消费者同时消费时,不能保证消费也按照A、B、C的顺序被依次执行。

所以RabbitMQ的解决方案就是为每一个消费者指定一个专门的队列,如下图:

上图中,只要消息按照A、B、C的顺序入队,那每个消费者获取并执行消息的顺序也一定是A、B、C。

注意,由于可能存在网络延迟的因素,生产者需要确保按顺序投递成功。

三、Kafka

首先, Kafka默认会保证同一个partition内的消息都是有序的 ,所以我们只要能够让生产者在发送消息时将需要保证顺序的几条消息都发送到同一个分区,那么消费者消费时,消息就是有序的。

生产者在发送消息时,会通过以下方式之一确定消息所属的partition:

  • 显式指定partition
  • 不指定partition,指定key:根据key的hash值与分区数进行运算,确定发送到哪个partition分区
  • 不指定partition,不指定key:轮询各分区发送

所以,我们只要采用 指定分区 或 指定key 的方式就可保证消息的有序性,如下图:

这种情况下,如果消费者内部是单线程去依次执行每个消息,那没有问题;如果是多线程执行,就需要考虑consumer内的消费有序性,一般可以利用内存队列来解决。

消费者内部多线程情况下保证消息有序的方案如下:

我们一般需要先进行压测,看下如果消费在单一线程下处理消息的吞吐量,如果一秒钟只能处理几十个消息,那实在是太低了,得考虑多线程方案。

四、总结

本章,我们介绍如何保证消息队列的消息有序性,根本思路就是两点:

  1. 保证队列内的消息FIFO;
  2. 保证一个消费者对应单独的一个队列;

在实际业务中,需要消息有序性的场景其实并不多。

标签:顺序,码哥,进阶,源码,消息,有序性,多线程,分布式
From: https://blog.csdn.net/smart_an/article/details/137391732

相关文章

  • Python爬虫之分布式爬虫
    分布式爬虫1.详情介绍        分布式爬虫是指将一个爬虫任务分解成多个子任务,在多个机器上同时执行,从而加快数据的抓取速度和提高系统的可靠性和容错性的技术。        传统的爬虫是在单台机器上运行,一次只能处理一个URL,而分布式爬虫通过将任务分解成多个子......
  • 太强了!分布式Elasticsearch集群数据迁移企业案例
    太强了!分布式Elasticsearch集群数据迁移企业案例原创 林致远 Linux运维之旅 2024-04-0408:31 广东 1人听过Linux运维之旅专注分享运维实用技术,内容不限于Linux系统运维、自动化工具、监控工具、日志采集、容器技术、测试工具、python、GO等技术分享20篇原......
  • 第六章 面向对象进阶——6-3 继承
    一,构造方法:this(…)-访问本类构造方法super(…)-访问父类构造方法 二,继承中构造方法的访问特点(理解)注意:子类中所有的构造方法默认都会访问父类中无参的构造方法子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,原因......
  • MyDumper/MyLoader的进阶玩法
    一、前言从mydumperv0.11.5版本开始,mydumper提供了--load-data参数,使用此参数导出的sql文件将不再是insert语句,而是loaddata语句。在MySQL官方文档中关于loaddata是这么描述的:Whenloadingatablefromatextfile,useLOADDATA.Thisisusually20timesfasterthanus......
  • Caddy进阶:因为Nginx占用了80和443端口导致Caddy无法启动
    日志里面有个红色的error,表示安装后没有启动caddy的服务。看了很多文章,感觉都没有把我当小白。自己折腾了几个小时,总算搞明白了。1、如果80端口和443端口被其它程序(比如Nginx)占用了,得先卸载Nginx。查看443端口被谁占用了:root@web005:~#sudolsof-i:443COMMANDPIDUSE......
  • Spark进阶(四)Spark性能优化和调优
    一、Spark的性能优化工具和技术Spark的性能优化工具和技术主要包括以下几个方面:数据分区和缓存:合理地将数据进行划分和缓存,可以提高数据的访问效率。可以使用repartition或coalesce进行数据分区,使用persist或cache进行数据缓存。并行度设置:通过调整并行度,可以提高Spark......
  • 加入云原生实战营(星球),带你进阶 Go + 云原生高级开发工程师
    过去1年,趁着闲暇时间,我创建了一个Go+云原生技术学习社群,旨在帮助你快速进阶为Go+云原生高级开发工程师,提高你的职场竞争力、扩展职业宽度,最终谋得一份好差事(进入大厂、升职加薪)。本篇文章,我来详细介绍下云原生实战营知识星球,让你对本知识星球有一个充分的了解,通过这些了......
  • 每日面经分享(python进阶 part2)
    Python中的装饰器和上下文管理器区别是什么?它们分别适用于哪些场景?a.装饰器用于在函数或类的外部添加额外功能,而上下文管理器用于管理资源的获取和释放。b.装饰器是一种用于修改函数或类行为的技术。适用于需要在函数或类的外部添加额外功能的场景,比如日志记录、性能监......
  • 中间件 ZK分布式专题与Dubbo微服务入门 6-13 acl - ip权限
    0课程地址https://coding.imooc.com/lesson/201.html#mid=12729 1重点关注1.1本节内容通过schema为ip的方式设置权限,只有指定ip才能操作 1.2关键代码//ip方式的aclList<ACL>aclsIP=newArrayList<ACL>();......
  • 中间件 ZK分布式专题与Dubbo微服务入门 6-12 acl -自定义用户权限
    0课程地址https://coding.imooc.com/lesson/201.html#mid=12728 1重点关注1.1本节内容通过schema为digest密文的形式设置用户权限,调用权限 1.2关键代码//自定义用户认证访问List<ACL>acls=newArrayList<ACL>();......