粉丝38.3万获赞110.4万


今天给大家分享一下这个顺序消费的一个问题啊,利用这个 raptampq 给大家演示一下,本期视频的一个关键词呢,就是顺序消费啊,消费者带货模式,以及说按 消息键,宝旭的一个思想,如果你都知道的话,就可以不用看了。那这里呢,我们首先来介绍一下什么是顺序消费啊?我们一般的一个消费,比如说订单超时关闭啊,这样的事情,对吧?我们不需要关注他的一个顺序,所以说针对于顺序消费,很多小伙伴可能比较懵啊,这里我举一个例子, 比如说有三条消息要发送啊,这三条消息呢,分别是针对于啊,同一个数据的一个新增、修改和删除啊,那这里就有顺序的要求,你比如说我还没有新增,你就去进行了修改和删除,肯定会出现业务异常的,对吧?这里的顺序指的就是啊这个意思,那如何去保证这个顺序呢? 一般我们会从这三个方面来考虑啊。首先说你发送消息的一个顺序,嗯,发送消息的一个顺序呢,大多数情况下是不做什么要求的,你如果说一定要保证的话,那就是 啊,去进行一个枷锁的一个操作啊,这里好,那第二个呢,就是对列中消息的一个顺序,就是我们将消息发给 mq, 在 mq 中他能够保证一个顺序吗?这个是由 mq 提供的,确实是可以保证顺序啊,因为对列本身就是可以顺序的。然后 最重要的一点就是消费者的一个顺序啊,这里是要由我们的程序来保证的,因为我们的消息啊,往往在进行消费的时候,大家的程序都是多个副本,我们同时去进行消息的一个消费, 那每个副本呢,他消费消息的速度都或多或少有点不同啊,就会导致我们的消费消息的一个顺序产生了一个问题啊,那如何去解决呢? 其实我们只要保证一个对立啊,只有一个消费者,这样的消息就可以一个一个的被顺序消费了啊。但是这样也有一个很明显的一个缺点啊,就是他的一个并发能力下降了啊,当然这个问题呢,就可以用这个消息键保序的一个思想,呃,举个例子啊,嗯,比如说我们 只有一个对列的前提之下,我们要做这种呃操作,那我们就只能发送到一个对列中去,对吧?但是如果我们有很多个这种对列,然后我们呢根据业务组建的一个 id 啊,去进行一个曲模运算啊,把得到的不同的结果呢,扔到不同的那个对列中去, 这个样子呢,就可以多个队列同时消费,而处理的却是同一批啊,同一类业务数据,这个样子就可以提升他的一个啊消费速度。可能啊,光那么说有点难以理解,我们来看一下代码啊,首先我们这里来看一下配置啊,配置这边呢,我们其实是创建了四个队列啊, 然后这四个对列在创建的时候呢,都是用了这样的一种方式去创建的,我们会给到他的一个参数啊,这个参数呢,其实就是单货模式啊,防止他多个副本同时去进行消息的一个消费啊。然后呢,我们这里的四个对列,然后我们在投递的时候,生产者他会根据消息的主见去进行一个什么运算, 然后啊根据得到的一个结果,我们来指定它的一个路由 k 啊,这样子这个消息就会投递到不同的一个对列中去啊,最终我们在消费的时候, 我们同时去消费了四个对列,这里相当于是写了四个方法去进行一个消费啊,啊,只是比较偷懒,就这么写了啊,这里消费的时候,我们就可以啊,直接拿到了四个对列里面的数据去进行一个消费啊,实际消费方法呢,并没有太大的一个出入啊,这里只是一个模拟延时的一个操作啊。 嗯,那我们这边测试测试,怎么测试呢?呃,比如说我这里呢,其实是进行了两层循环啊,首先第一层循环呢,它代表的是我们有序的消息个数啊,零到一个消息, 我们要求这个消息是能够被一个一个的消费。然后第二层循环,其实我们是把它来当做这个消息编号的,就是我们会根据这个编号来给他投递到不同的这个对列中去啊,就是 按消息逐渐保序的一个思想,我们的逐渐指的就是它啊发送的时候根据这个 id 来进行一个保序的一个操作啊。然后呢这里的一个默克方法呢,其实它就是模拟多个副本啊,因为我这里启动了,而没有去执行其他操作,那我们这个消费者是一直活着的, 所以在这个生产者生产的时候,他自身的消费者和啊这个测试启动的消费者都会形成一个竞争关系,然后我们来看一下他的一个情况, 先启动这个木盒方法,然后再启动我们这个的一个测试, 这里我们的单测试已经跑完了,首先可以看到啊,我们的这个发送方法的这个消费者,他没有任何的一个输出,而我们之前跑了这个幕后方法,他却进行了一个消息的消费,对吧?然后我们来看一下效果,嗯,首先说我, 我们是根据这个编号啊,将消息投递到不同的对列中去,然后我们这里只看编号零的,然后过滤一下,嗯,好,这里呢我们可以看到他的消息啊,是按照顺序的去给我们进行了一个消费,对吧?然后我们再看一下其他的,比如说编号三的, 也是按消息也是按顺序的去进行了一个消费,对吧?而我们不同的对列之间啊,他的消费顺序却是不一样的,对吧?那这里其实也是说,我们就是能够通过这种方式去保证了一个顺序,并且通过按消息鉴宝序的一个思想提高了他的一个消费速度。 而我们的一个单薄模式呢,其实啊,在管理后台这边啊,如果说你在这个 m q 的管理后台这边,你会看到啊,当你有多个消费者同时注册上来的时候,只有一个消费者会去消费,而其他的消费者会进入到 一个等待的一种模式啊,这就是单活模式的一个应用。好,那今天的分享就到这里,有需要代码的小伙伴可以到主页上去拿一下,我们下期再见。

因为五年工作经验的小伙伴在面试的时候被问到这一个问题,他让你对 rap 的门口架构远离的理解,当时呢,这位小伙伴只解答说我只会用远离,并没有关注过。那今天呢,我给大家分享一下我的理解。 另外呢,我花了一个多星期准备了一份十万字的面试题解析,配套完档,想获取的小伙伴可以在我的个人主页简介中找到。 要回答这个问题呢,首先要知道 rappermike co 架构中的几个核心的角色,他们分别是 paradoca..................................constina curry 这个是欠记帮顶 we host。 那么这些角色之间是如何协调工作的呢?下面呢,我们来看一下这一个动画。首先呢,是第一个和第二个,不是大哥的和坑数码,那么分别是消息的生产者和消息的消费者,这就是 所有的消息中间键都有的两个角色。我在这里呢就不做过多介绍了,那重点来看呢?第三个叫布洛克,中文翻译过来呢,叫做代理或者是中介,我们可以把布洛克理解成为是安装拉皮的门口的一个服务器,这就是一栋用来存储和转发消息的房子。 第四个呢就是可耐克省连接,那无论是生产者发送消息还是消费者接受消息,都必须要跟布洛克之间建立个连接,克耐克省呢,就相当于是 tcp 的长连接。第五个呢是天暖通道, 如果所有的生产者发送消息和接通消息,每次都要去创建和释放 ttp 常年级的话,那么对于布拉克来说,肯定会造成很大的一个新能消耗,也会浪费时间。 所以呢,在 am q p 协议里面呢,引入了一个千等的概念,它相当是一个虚拟的连接,这样的话我们就可以在已经连接好的 tcp 长连接里面去创建或者是 释放签了,这样的话就大大减少了资源的消耗。那不同的签了呢,是相互隔离的,每个签了呢都有自己的编号,对于每个客户党的现成来说,签了就没必要去共享了,因为他们各自有自己的签了。 另外一个需要注意的是, china 是 rabymik 原声 app 里面最重要的一个编程借口,也就是说我们要定义交换机对列绑定关系,发送消息,消费消息交易的都是 tenan 借口送的方法。 第六个是快点对练,他专门用来存储消息,那么快点呢,也是生产者和消费者的一个纽带,生产者呢,发送消息或存到对列中,而消费者呢,也是从对列中来消费消息。 第七个呢是 x 庆吉,叫交换机,相当于是消息的路由器,那 x 庆吉呢,不会存储消息,他只是做一件事情,就是根据规则来分发消息。第八个呢就是帮顶翻译过来叫绑定, 那么一个是见解和存储消息的对列呢,必须要建立一个绑定关系,并且呢每个对列都要指定一个特殊的标识,那一个是见解和对联呢,它是一个都对多的一个绑定关系,也就是说一个加换机的消息会落油给多个对列,那么一个对列呢,也可以接受来自多个加换机的消息 在绑定关系建立之后呢,生产者发送消息到一个信息,那么也会携带一个特殊的标识,到这个标识跟绑定的标识匹配的时候呢,消息呢,就会发给一个或者多个符合规则的对列。 最后一个呢就是微 house, 他的全身叫做 wei 错 house 的虚拟机,他为了去解决不同业务系统之间的一个消息隔离, 也为了去节约硬件成本。所以呢,我们可以利用 rapuncle 的微耗子的来实现资源的隔离和权限的控制,那微耗子的功能和其他编程里面中的 nais 笨死是比较类似的。以上呢,就是我对 rapunanico 架构 远离的理解,小伙伴们你是不是也理解的更加透彻了呢?我是被编程耽误的王一汤,如果我的分享对你有帮助,请你动动手指,一键三年分享给更多的人,关注我,面试不再难!

好,同学们,接下来我们就开始今天的第二章, rabbit mq 的快速入门, 在这一章当中啊,我们会去了解一下 rabyten q, 并且呢去安装它,然后我们会给大家介绍一下 rabytem q 当中的常见消息模型,最后呢我们还会带着大家动手呢,去写代码,看一看 rabyten q 它如何实现这种意步的消息通讯。 好,那接下来我们就进入第一部分啊, rabbit mq 的一个简单认识和安装。 rabbit mq 啊,是一个基于啊浪语言开发的开源消息通讯中年间, 而阿浪语言大家可能不太熟,这是一个面向并发的变成语言,天生就是为了分布式系统来设计的,而 rabbit mq 基于他来 完成,自然就具备了这些个特征,那因此他的一个性能,吞吐量都还是相对来讲不错的啊。但 rabomq 最擅长的其实是消息的可靠性,稳定性,整个系统的这种高可用啊。 那这里呢是 mq 的一个官方网站,我已经提前打开了啊,大家可以看到啊,这个网站啊,这上面有一群的兔子,那另外呢,这边呢还会有一些文档,那大家呢,如果想要去学习 mq 最好呢基于这个文档去进行学习啊, 好,那现在我们再回到 ppt 啊啊,那在这里呢,我们就带大家去安装一下 rabyten q 了啊,安装方式呢,可以参考课前资料, rabyten q 的部署指南, 我们打开看见资料可以看到呢,这里有一个文档,然后咱们 q 不输指南,我们把它打开。 好,那接下来呢,我们就来完成这个部署,这个部署呢有单击部署和集训部署两种方式,我们呢就来看单击部署就行了,我们将在三斗司训练机当中利用刀砍来进行部署,因为这种方式是最简单最方便的嘛。 啊,那第一步肯定是要获取刀壳的镜像了,那么这个镜像大家可以去直接 po 拉取,也可以从科研资料当中去导入这个踏包,而导入的方式我们之前已经讲过了啊,就是利用这个刀壳 low 的命令来完成导入,对吧? 那么下边呢,我们就来打开我们的训练机,我们通过 docker amidis 先查看一下我们本地印象。啊, 好,可以看到,我这里也没有 mq, 对不对?那接下来呢,我就按照刚才文档中所说把它导入一下,那我们打开, 哎,课前资料这里呢有一个套包,现在呢,我们把它上传上来啊,那上传到哪里呢?我们上传到这个 tmp 的目录吧,这临时目录嘛,我们把它拖上来。 好,我们可以看到一百多兆啊, 好,上传完成,完成以后,我们再次回到这个小控台,然后通过一个命令来安装啊,我们先进入天平部路看一眼,有的吧,怎么导入?同学们,命令是什么?告诉我 刀干什么 low 的,干啊,哎, mq 点踏,哎,很好啊,走 好。经过一番安装,我们发现导入成功了,我们通过 docker images 查看一眼,发, 发现这里导入了一个名为 rap mq 版本呢,是三杠 management 的这样一个镜像,已经成功导入了。好,那第一步我们就完成了,我们再次回到文档看一下, 导入了以后,下一步自然就是安装 mq 了,运行这个刀口 rad 命令吗?那这个命令呢?在这我已经给大家贴好了, dock run 杠一 杠一呢是给我们的 mq 设置一个黄金变量,黄金变量我这配了两个,一个是 user, 一个是 password, 也就是用户名和密码。将来我们需要去访问 mq 或者是登录他的管理平台,都需要用这个账号和密码, 再往下干个 name 呢,是给他起个名字,这块呢是配置主机名,不配呢,也没问题,但是如果将来做集群部署就要配这个东西了。杠批呢是他的端口映射,这里我们开放了两个端口啊,一 个是幺五六七二,这个呢是 raby 咱们 q 的管理平台的端口,他会给我们提供一个 ua 界面,我们去管理起来就非常方便了。第二个五六七二呢,是将来做消息通信的一个端口,也就是说我们将来发消息,收消息都要通过这个端口去建立连接。 杠地是后台运行,最后呢是镜像的名称。好,那下边呢,我们就把这个命令啊给他敲一下,我们回到下个控制台,然后在这呢进一个粘贴回车 好容器创建完成,我们通过刀砍 ps 查看一下是不是成功的启动起来了。启动起来以后呢,我们就可以去访问了啊,他端口我们刚才讲了,幺五六七二是他的什么端口啊?是不是空了台端口,所以我们只需要在浏览器里访问这个地址就能够看到了 啊,那现在呢,我们就打开浏览器,在这里输入训练基地地址啊,幺九二点幺六八点幺五零点幺零幺,端口呢是幺五六七二,大家记住这个端口啊, 好,回车可以看到呢,成功的进入了 raby temque 的管理界面了吧,这里啊要输入一个账号和密码,我们刚刚在刀口 rat 命令中啊,指定的是 it cast, 密码是一二三三二一,点击 log in, 这样呢就成功的登入了我们 rabbit mq 的一个管理平台了。同学们, 那么在这个界面当中有很多的东西啊,大家现在都不认识啊,没有关系,等一会呢,我们就会一一给大家介绍。那首先呢,这第一个界面叫 overview, 就是总懒,那么这个界面呢,主要就是 mk 的一些节点的一些详细信息,当前我们是单节点运行,没有集群吧,所以节点中只有一个,然后呢,后边是他的这个硬件的一个信息啊, 然后在这儿 connection, connection 就是连接,将来无论是消息的发布者还是消息的消费者,都应该跟我们的 mq 键连接吧,所以这个 connection 呢,就是连接, 而前头呢是一个通道,将来我们建立连接了以后,一定要创建一个前头通道, 然后生产者或者是消费者才能基于钱脑完成消息的发送或者是接收啊,所以你可以认为钱脑是 mq 当中做消息发送也好,接收也好等等各种操作的一个具体对象了啊,将来每一个连上来的人都应该去创建一个或多个通道啊,再往下呢, x 欠着,这个叫交换机,他是一个消息的路由器啊,就跟咱们那个教室里边的路由器交换机效果是类似的。然后 q 呢,就是对列了, 对列就是来做这个消息存储的啊,那现在呢,可以看到还没有任何的对列吧?刚才交换机看到还是有一些交换机的啊,但是没有对列 好,那最后奥特曼呢?是叫做管理,那么在这个界面当中,我们可以去管理当前这个呃用户信息啊,比方说我现在是不是有个用户叫 it 卡死他呀?那我还可以干什么呢?在这创建更多的用户, 比方说我现在要创建个用户,我只需要在这点击爱的 uzer, 然后在这呢给用户起个名字啊,比如说就叫李四,然后给他起个密码,比如说一二三,一二三,那这样一个新的用户信息就填好了,这里还可以给用户分配一个这个 呃角色啊,比如说艾特曼呢,是超级管理员啊,这里的 money 特呢,就是一个系统监控的啊等等,我们可以去选,比如说选艾特曼啊,超级管理员,那么这个信息呢,就成功的提入到这里了,最后点击艾的 user, 那么我们这个用户就添加成功了, 但是你发现啊,当我新增一个用户以后,他其实是没有任何访问权的,看到没有?没有 no access, 那这个是因为什么呢?这里有一个说明啊,大家可以看到叫做 virtue house, 虚拟主题 啊,虚拟主机啊,虚拟主机是什么呢?是我们 mq 当中的一种逻辑划分,将来我们会有很多个用户,对吧?那这个埃迪卡斯的用户,他来操作我们的 rabbit mq, 创建自己的队列,自己的交换 机等等,那么我们的李四用户也来做这些事,那这两个人在操作过程中是不是有可能产生冲突啊, 那为了避免这种问题的发生啊,我们就有一个叫 virtue house 虚拟主机的概念,那通过虚拟主机对不同的用户进行一个隔离,大家互相看不到对方的东西,这种呢就称之为多租户的一种处理了,对吧?是一种隔离,这就是虚拟主机的概念了, 虚拟主题目前啊默认只有一个,就是斜杠,那我们还可以通过在这玩手 houses 创建更多的虚拟主题,比如说添加一个新的名字呢,也可以随便取,比如说就叫杠, it cost, 然后在下边呢,还有这个虚拟主机的一些描述信息啊,你也可以写,也可以不写好,点击添加,你看一个新的虚拟主机是不是创建好了,现在我们再次回到 u 字界面,在这个界面当中呢, 我们可以看到艾迪卡斯用户具备杠和艾迪卡斯访问权限,而李四还是没有任何权限,而你点击用户信息了,就会进入用户的视力界面,你可以给他分配权限啊, 怎么分配呢?比如说我让他访问爱迪卡斯特,那这样呢,点击赛的 permission, 他就具备了对爱迪卡斯的这个虚拟主题的访问权了。那我们再次返回到优乐界面,可以看到是不是有访问权了, 然后呢,我们还可以点击到交换机的界面来看一眼,在这个界面当中,你会发现啊,虚拟主机杠和 airicast 他们所具备的信息是不是一样的, 也就是说呢,这里面虽然名称是冲突的,但是呢,因为虚拟主机不同,他们是不是给被隔离开了?一般情况下,同学们,我们回答的跟你见面每一个用户应该由自己独享的虚拟 主题啊,同学们能理解的意思吧,好比方说我的艾迪卡斯的,我点进去我就让他只具备杠的防御拳,不具备这个艾迪卡斯的防御拳,那这样一来,他们两个的业务是不是就被隔离开了,互相就看不到对方的这个内容了? 那这就是我们的这个多租户以及这个虚拟主机的一个隔离了。行了,那 mq 的安装就完成了,下面呢,我们回到 ppt 来看一下我们这个 mq 的一个整体结构啊,刚才其实我们已经给大家做了简单介绍了,这边 population 呢,是我们的消息发送者,看修门呢,自然就是我们消息的消费者, 他们的意思呢,将来会把消息发送到 x change, 也就是我们的交换机,交换机呢,负责路由,再把消息投递到 q 对列,对列负责斩存小。 而后呢,我们的消费者再去从队列当中获取消息,然后处理消息,整体呢,就是这样子的啊,那你会发现呢,这里有一个叫 vershow house 的一个概念虚拟主机吗?将来我创建了一个用户以后, 他呢会有自己的一个虚拟主机,再创业,新的用户再有虚拟主机,那各个虚拟主机之间是相互隔离的,看不到的,这样可以避免干扰,这就是整体 mq 的一个架构了啊, 好,那最后呢,我们来做一个总结, rabbitom q 当中的几个概念,第一呢是 channel, 是操作 mq 的工具啊,你做消息的发送也好,接收也好,都必须要用的 channel。 x change 是消息陆游,将来消息发送给他,他在陆游给对列。对列呢?当然就是缓存消。 记得了 versa house 的虚拟主题是对 q x 限制等等这些东西资源。那个逻辑分组啊,将来呢?给它隔离起来,不同用户可以访问不同的虚拟主题。好,那我们这节课的内容就到这里。

我们再来看一下这一道 rap and q 的面试题,它来自于腾讯啊,对应的薪资是二十五 k 岗位高级开发。 rap and q 当中的 q, 它存放的 message 是否有数量的限制?这个限制是多少呢? 首先大家应该要知道,其实在 rep and q 当中,这个 q 对应的就是存放 message 的一个队列,一般情况下面我们可以这么去认为,在这个 q 当中它应该是一个无限场 啊,就是作为我们 rapinq 当中你存放的这个 q 啊,理论上讲来说他应该是没有限制啊,当然回答这道问题的话呢,你不能这么绝对啊,我们可以看到, 嗯,你怎么去回答呢?都不是太合适啊,比如说你回答没有限制,好像呢也是不行的啊,但是默认情况下面他是没有限制的,他可以 通过一个参数来进行限制啊,他也不是我们经常所说的什么幺零二四啊,四零二八啊,还一些其他的数数字。我们可以看到,在这道问题当中,默认情况它是无限制,就是你 rap q 当中的内存有多大,那这个 q 它就可以多长。 但是呢,我们知道如果你的消息过多的话,他肯定会导致我们 rapid q 处理这个消息的效率他会下降,因为这个对立过长的话, 那么我们知道第一个内存占用的多,第二个的话呢,你要把这个数据从这个内存里面拿出来, 相对来说呢,它效率要低很多,所以我们可以通过对应的参数来限制这个参数,叫做 x 杠 max 杠 nus 啊,这样一个参数,这个参数的话呢,请注意这个参数它是限制消息的条, 比如说这个设置成一百万,那么对立当中的消息就不能超过一百万。另外的话呢,还有一个限制参数叫做 x 杠 max, nurse gun bites, 这个呢是限制我们消息的总量, 比如说我们的消息总量限制成两百兆,那么在对列里面啊,单独的一个 q 里面,他就不能超过两百兆,所以我们可以通过两个参数,第一个参数是消息的调数,第二个参数是消息的总容量啊,两个方面对 robinq 当中的 q 进行限制, 所以的话,当面试官问这样的问题的话,他其实就是有一定的欺骗性,就是他问你的限制是多少?很多人呢?可能是啊,去绞尽脑汁想一想,哎,这个 rapton q 当中的这个 message 是不是限制是多少呢?随便猜一个数啊,如果这个数量 就是你随便说一个的话,那么这个答案明显就是错误的。你应该说默认情况下面他是没有限制,但是我们可以通过两个参数 来控制一下 rap q 当中这个 q 的数量和 q 的容量,通过这样的方式呢,我们可以去稍加限制,所以呢,这就是这道面试题他回答的一个重点和核心。

今天我们基于圣特 o s 七安装消息中间键 rapt m q。 好,我们先看第一步, 首先我们要把 rapid mq 所依赖的语言环境做对应的安装 好,那我们先看第一步,第一步我们要去执行这样一个命令啊,就是把对应的这个压浪所依赖的环境先做对应的安装 好,我们执行一下啊,好,这里就代表我们这个一带的环境啊,已经安装好了。好,那接下来我们去执行另外一个命令啊, 我们直接把 e r 浪这个对应的这个安装包先做一个解压。 好,我这里已经解压了啊,所以这个命令我就不去做对应的执行 好了。第二步的话,我们先进入到这个解压的这个包里面好,然后再去做对应的编译啊, 好,执行这个命令好,出现这样的一个界面啊,就代表我们的这个, 呃,已经编译成功了。好,编译成功之后,我们这里要去做一个安装好,执行 好,这里就代表已经安装成功。好,那接下来我们要把对应的这个环境变量去做相关的配置, 因为刚刚在安装的过程中啊,这一步 没有做相关的提示,所以,所以我们对应的这个命令啊,不用去做执行。好,那我们接下来去编辑我们的这个环节面料 好,然后 在这个文件的最后面啊,好,在这里把对应的这个配置把它加上 好,然后在 e s c 冒号 w q 啊保存就可以了,然后最后的话直接执行这一个 mini source, 然后环境变量的这个文件名。 好,这样就可以了啊,然后最后的话,我们直接输入 e r l 检查看是否安装成功。 好,可以看到这里啊,这里有对应的一个版本,对不对?那这个就代表我们的这个压浪已经安装成功了。

rabbit mq 的事物消息,那么在这个 rabbit mq 里面,他是支持这个带事物的一个消息的啊, 我们这边说的这个事物跟我们数据库中说的这个事物呢,也是一样的啊,都是呢,会保证这个 acid 的一个特性啊, 他这个事物跟我们数据库的这个事物很像啊,就是可以开启这个事物,然后呢提交以及回滚,他都有了这个相应的 api 一个支持啊, 那么这个 raby 的 mq 他的这个事物消息了,我们要注意一点啊,这个事物消息啊,他的这个性能呢,通常不太高,这个我们要知道,但是呢在有些场景下面呢,又必须要去使用这个事物消息, 比如说我们这个生产者,对吧?把这条消息发出去之后,可能呢,我后面呢还要做一些处理啊,首先是发出消息,对吧?就是剩的出一条消息,那么我后面呢可能还要做一些啊,一些逻辑处理, 那么可能我这整个的呢,我需要在一个事物里面啊,也就是说后这是这条消息啊,发送成功与否,那么跟下面的这个极其相关,对吧?如果我下面执行失败了,那么我可能这条消息呢,我就,呃相当于呢我就不发送了,那么这个时候怎么办呢?你已经发出去了,怎么办?呃,对不对啊? 那么也就是说这个 raby mq 呢,实际上呢,他也提供了一种回滚机制啊,就是说如果说你下面的这个逻辑执行错误,也可以了,让这条消息了,把它回滚回来啊,那么这个是啊, raby mq 的这个事务消息,当然呢,这个事务消息的话啊,我们通过就是之前讲的这个 raby mq 里面的另外一道面试题啊,就是这个,呃, 叫做一种什么事物的一个确认机制啊?确认机制就是这个 comform, 那么这个 comform 呢,也是其实也是可以保证这个消息的一个可靠性嘛,对吧? 但是这个坑缝的机制啊,他呢是一一种异步机制,特别是在发送方啊,在发送方呢是一种异步机制嘛,那么发送 把这个消息发出去之后啊,那么呢还可以接着发送消息,只不过是说了这条消息了发送之后呢,如果成功了的话,如果成功投递到这个服务端 啊,这,那么这个服务端呢,会来回掉这个客户端的一个接口吗?然后来告诉你这条消息呢已经发送成功了,当然这种呢可以确保这个消息呢一定会被投递出去, 但是对于我们这种事物场景来说啊,这种就是严格要求,这个是呃数据一致的,对吧?就说比如说我下面这些要是处理失败了,我这条消息呢,我就不能够被啊消费消费端的消费到啊, 那么通过前面这种确认机制其实是做不到的,对不对?因为这个消息发送出去啊,那么你极有可能生产端还没收到这个东西了,消费端呢就已经把这个消息给消费了。而这边呢 如果是在我们这种场景下面,那绝对是啊不允许这种情况发生的啊,啊,特别是还还有的一种场景,就是这个我们这个生产端呢,把这个消息发送出去之后,可能呢这个消费端呢可能还要来调这个生产端去查一些东西,对不对?比如说我们还可以,还可以通过这个接口去进行这个呃交互啊, 不仅通过 mq 交互,可能还有接口进行交互,那我这条消息一发送出去,我后面的事情还没做完呢,如果这个时候消费端就来查这个数据的话,那么极有可能此时查到的数据呢,也是不对的数据。所以说呢,这个事物消息呢,主要是保证啊,这个消息的这个发送,跟我生长端的这个逻辑呢,保持在一个事物里面, 那么这个逻辑回滚的话,那么我这个消息呢也要能够撤回来。那么这个 raby 的 mq, 他这个事物消息是怎么实现的了?实际上他的原理呢,很简单啊,那么我们简单来看一下这个,现在来 看一下他的一个简单的一个用法啊,用法呢很简单,我们在这个信道上面去设置一个就是开启事物啊,那么你当你调完这个 api 之后,实际上呢,我们这个客户端呢,就会去啊, 访问这个服务端啊,通知这个服务端开启一个事物,那么此时呢,我们就可以发消息啊,可以发多条,还可以发多条消息。然后呢发完之后呢,你可以去进行提交事物,但在这中间呢,你还可以做其他的一些操作啊,然后提交事物,或者是回滚事物。好,那么他这个原理呢?其实是什么呢?就是 我们在开启了一个事物之后啊,那么你此时发送的这个消息啊,其实并不是真正的发到了这个 q 里面,我们说这个消息呢,他是会发到这个 q 里面,对不对?这个交换记忆啊?对应的这个 q, 然后呢消费当中从这个 q 里面去订阅消息啊,但是如果你开启事务了的话,他此时呢并不是直接发到了这个 q 里面,而 是发到了一个专门的一个队列啊,应该是叫做 rp, 呃,一个什么什么啊?一个,一个比较长的一个队列名字啊,他会发到这么一个临时队列中,把这个事物消息啊发到这里面去。那么 只有当你真正提交事物了啊,你做了事物提交,那么呢他会就将了这个消息从这个对列中呢移到这个真正的这个 q 里面,那么此时消费端呢才能够消费得到。这其实就是这个 raby 的 mq 实现这个事物消息的这么一种机制啊,就是维护了,相当于维护了一个另外的一个队列啊,好, 那么这个事物消息他如果是跟我们的那个,呃, 之前讲的这个,呃, raby mq 中的另外一种机制,就是这个 conform 机制,就是我们这个啊发送端的这个确认机制,对吧?那么通过这种机制呢,实际上是 这种机制呢,他的效率会更高,因为这种机制呢,他是一步的消息发出去之后,他就不管了,对不对?可以接着再去发消息,然后呢 这个服务端呢会接着再来回掉他,对不对?然后告诉你这条消息成功了,但是呢这个事物的话,他是一定要这个提交,一定要提交完成,那么呢才才这个消息才是真正的进入了这个 q, 同时呢你这个提交呢,也会去连这个服务器啊,也会去连 连服务器,那么中间的这个消息发送啊,包括这个开启师傅啊,都会去连服务器,所以说呢,他这个连接次数呢,会比了 这种坑粪模式会更多啊,这个连接次数会更多,所以说这种事物消息他的这个性能呢,会远不如这种坑粪模式,但是这个坑粪模式呢,当然他也有呃做不到的一些场景,对吧?所以呢我们要去区分一下啊,那么你明白了这两种功能的一个啊,一个实现的话,明白了他的一个逻辑啊,那么什么样的场景该使用哪种机制了? 应该要就可以做出这个选择了,对不对?那么呢但是要明白的是,如果两种都可以选的话,那么肯定优先呢选这个 通风,因为他的性能更高啊,当然这个是在发送端了啊,如果是在消费端的话,那么我们此时啊也可以是消费端的消息呢,提交这个 ack, 我们讲这个消费端呢也有这种消息确认机制吗?对吧?就是消费端呢,我设置这个手动提交,就是将这个奥特 ack 啊设置为 phose, 也就是说我消费端的手动的去提交这个 a c k, 那么你提交完这个 a c k 啊,这个呃 rap m q, 这个服务端呢才会把这条消息删除啊,那么如果你要是不提交这个 a c k 的话,他可能就不会删啊,他会一直等你处理完返回这个 a c k, 那么 这个如果说我们要是把这个返回这个 ack 啊,如果是放到这个事物中去做的话啊,就是说我如果嗨起了一个事物,然后呢去处理这个 ack, 最后呢去提交这个事物,哎,那么此时的话就以了事物提交为准啊。就是说,如果说你既开启了手动提交,也开启了事务,那么最终这个啊, raby mq 服务端的这条消息,他的这个删除,以,他是以你提交的 a a c k 为准呢?还是以事物提交为准呢?其实是以事物提交为准啊,那么只有当你事物真正提交之后,这个 a c k 呢,才算是返回了啊。如果说你此时要是回滚的话,那么呢这条消息呢,还是会回到这个对列中,他并不会把这条消息删除啊, 哪怕你返回了这个 a c k, 那么你最后回管他的话,这条消息呢,也是不会被删除的,他还是会在对列之中啊。好,那么这个是手动提交,那么如果是自动提交的话,如果是自动提交呢?他就不支持事务啊。如果你设置的是这个奥特 a c k 等于处的话,那么呢你开启 事物也是没有用的,那么呢 ack 一返回,事物马上就删除了,那么你后边的事物回滚也就没有,呃,也就回滚不了了啊。好,那么在这个, 在这整个事物的这个逻辑中啊,如果其中的任意一个环节出了问题的话,那么他呢会抛出一个 l 异常,就是我们在这个提交这个事物之前,对吧?他会抛出一个 l 异常啊,那么用户呢,可以去拦截这个异常进行的这个事物的一个回滚,或者是决定了要不要啊进行这个 呃消息重新的发送啊,那么这个需要知道,就是我们什么时候就进行这个事务回管,可以去啊踹开取一个 l 异常啊, 然后呢这个事物消息呢,会降低这个 raby 的 mq 的性能可能会降低好几倍啊,因为呢你每一条消息都意味着好几次连接啊,好,那么这个是 raby 的 mq 中的这个事物消息,那么这个事物消息呢?其实 我们之前的那个呃消息确认机制啊,有那么一点相像,但是呢他就是所能够保证的是这个事物的这个 啊,保证了事物的这个 acid 特性呢,他会做的更加的好。而我们之前讲的那种确认机制呢,实际上是一种可以认为,呃,他是一种补偿 机制啊,但是,呃还不算是真正的补偿机制,他是事后才来通知你的啊,他保证不了你本地的这个啊,逻辑跟这个消息发送的这个原则性,对吧?但是如果是你开启这种事物的话,他就可以保证呢你这整个事物,对吧?这个消息的啊发送跟你这个本地 处理的这个逻辑之间啊,它是一个原子操作,那么这个就是这个 rabbit mq 中的这个事物消息机制。

rabbit mq 如何实现高可用?哈喽,大家好,我是麦克,一个工作了十四年的加瓦程序员,关于这个问题的解析和高手的回答呢,我已经把它整理到了一个二十万字的面试文档里面,大家可以在我的主页去领取。下面我来分析一下面试官对于这样一个问题的考察意向。 这个问题呢,就是简单的考察 rapton q 相关知识点的一个了解,难度呢并不大,主要是考察三年以上开发经验的同学。但是这个问题只是一个切入点,我认为接下来会根据求职者的背景和在实际应用中对于 rap and q 的一个使用程度, 去针对性的做更进一步的深度考察。在分布架构下,高可用是一个最基础的设计。也是说啊,一旦依赖的某个服务出现部长,不能影响业务的 正常执行。 rap 的 mq 呢,提供了两种情绪模式,第一个是普通的情绪模式,第二个呢是镜像情绪模式。我们先来看一下普通的情绪模式,在这样一个情绪模式下呢,各个节点呢,只同步原数据,不同步对列里面的消息, 其中的原数据包含对立的名称,交换机的名称和属性,交换机与对立的绑定关系等等。当我们发送消息和消费消息的时候呢,不管请求发送到 rapper 集群的哪一个节点,最终呢,都会通过原数据去定位到对列所在的节点,去存储和拉取数据。 很显然,这种提醒方式呢,并不能去保证 q 本身的一个高度用,因为一旦 q 所在的节点挂了,那么这个 q 的消息就没有办法被访问了,那么它的好处呢,是可以通过多个节点去分担了流量的压力,提升了消息的吞吐能力。 第二种呢是镜像集群,它和普通集群的区别在于,镜像集群中的 q 的数据会在 raptingq 集群的每个节点都存储一份,一旦任意一个节点发生了故障,那么其他节点仍然可以继续提供服务。 所以这种集群模式下呢,实现了真正意义上的 q 的高可用。最后啊,在镜像的集群模式下,我们可以通过 keep alive 加上 h a proxy 来去实现 rapperm q 集群的复载均衡。 像这样一个结构,其中啊, h a proxy 呢,是一个支持四层和七层的复载均衡器,可以实现 rapuncle co 提出的一个负载均衡。同时,为了避免 h a proxy 的一个单点故障啊,可以在前置增加一个 k plug 来去实现 h a proxy 的一个储备。 如果 h aproxy 主节点出现故障,那么备份的节点就会接管主节点提供服务。 kvlin 提供了一个虚密 p 业务,只需要去连接到虚拟 ip 就可以了。好了,这就是 rapunq 常见的高可用的一个时间方案。那么在面试的时候,我们应该怎么去回答比较好呢? 好的, rabbit mq 高可用实现方式有两种,第一种是普通的集群模式,在这种模式下,一个 q 的消息只会存在于集群的一个节点上, 集群里面的其他节点会同步 q 所在的节点的原数据消息。在生产和消费的时候,不管请求发送到集群的哪个节点,最终都会由陆游到 q 所在节点上去存储和拉取消息。 这种方式并不能保证 q 的高可用性,但是它可以提升 rabbit mq 的消息吞吐能力。第二种是印象集群, 也就是集群里面每个节点都会存储 q 的数据副本,意味着每次生产消息的时候都需要把消息内容同步给集群中的其他节点。这种方式能够保证 q 的高可优信,但是集群副本之间的同步会带来性能的损耗。 另外,由于每个节点都保存了副本,所以我们还可以通过 ha roxy 实现负债均衡。以上就是我的理解, 大家知道该怎么回答了吗?如果你喜欢我的作品,记得点赞、收藏加关注,我是麦克,咱们下期再见!

rep q 如何保证消息不丢失?我们首先来看一下 rep q 它的一个发送流程图啊,作为一个生产者,首先要把这个消息发送给 rep q 里面的一个叫做 exchange 的东东,所以这是它的第一步。然后第二步的话呢,这个消息它会被分发到对应的对应的里面,这是第二步。 然后呢,第三步的话呢,这个消息会被投递到对应的消费者,所以这是 rapling 他的一个工作流程。那么如何确保消息不丢失呢?其实要站在四个点,首先第一个点,我们要确保第一个消息要到 mq, 也就是说你进行发送的时候,至少这条消息要到 mq 里面来。 好,这是第一点。第二点的话呢,我们要确保消息能够路由到正确的队列,因为这个交换器啊,他就是类似于路由器的功能,他负责消息的路由。所以呢,在第二步里面,你要确保这个消息能够路由到正确的队列啊,如果, 如果说没有队列可以入游,这条消息有可能丢失。好,这是第二个。第三个的话呢,就是这个消息要在队列中间进行正确的存储,因为你作为 rapinq, 他有可能发生荡击或者发生重启, 所以呢,一般情况下面我们要把这个消息啊做一定的持久化,所以这是第三步啊。第四步的话呢,就是我们要把确保这个消息啊能够正确的投递到消费者。那么作为 rapinq, 他一般来说默认情况下面就是消息你发送给消费者 consome, 那么我就会把对应的这个消息从消费者里面进行删除, 但是有一种可能性就是消费者在消费消息的时候,他可能抛出了异常,那他一旦抛出异常的时候对不对?这个消息是没有被成功的消费的,但是呢,这个消息却从 reptile 里面进行了删除啊,所以呢,一般来说我们要去控制下异常,以及呢可能要进行一些重发机制。好, 现在我们来进行依次的讲解。首先第一个的话呢,如果你要确保消息到 m q, 你要使用一种发送的模式,叫做发送方确认的模式,那么发送方确认的模式怎么玩呢?我们来看代码, 好,这个呢就是我写的一段 rubbing q 的一个发送的代码啊,你可以看到我写了一个 rust ctrl 呢, 一个专门英语可以在浏览器里面直接访问到的一个 ctrl 呢,一个请求类啊。然后这个时候呢,我们对应一个路径叫做 derek, 如果说你发送 direct 的消息,他会响应在这里,然后我使用 spend boot 里面叫做 rep and q tablet 点 covent and send 这个方法向 rep 进行发送消息啊,发送到一个 direct exchange 交换器,然后对应有对应的建值,有对应的发送消息的本体。这个时候为了确保我相信能够到 q, 应该怎么做呢?那么我们来看一下 replica 的配置。 replica 的配置情况下面大家可以看到,首先的话呢, replica 它会使用连接,在连接的时候我们要设置一个这样的开关啊,这个连接里面叫做 connection factory, 要设置 publish come from 这个开关,把它设置为 two, 也就是意思我们的消息发送确认开关要打开好,这是第一个点,然后第二个点的话呢,在我们发送的这个 template 里面,我们要设置一个消息发送的回调函数,也就是我们要设置一下 come from call back 的回调函数,那么它具体的回调函数是怎么写的呢?来看一下啊。这个地方,当然我是用的一个艾特病,你也可以单独写个累啊。这个呢是 rubbing cutember 里面提供的一个 come from callback 的回调函数,在这个回调函数里面呢,它有一个 come from 的方法。在这个 come from 的方法里面呢,我们拿到对应的 a、 c、 k, 也就是说如果消息已经成功的发送给 mq 了,这个 sk 肯定会等于处,那么这个时候我们可以不处理,或者是稍微打印一下,其实这个消息呢,已经发送给 mq 成功了。 另外的话,如果这个 ack 他不等于处,那么我们就需要去考虑重发。所以呢,这个地方可以进行对应的异常处理,或者是专门写断代码,专门处理来那些发送失败的消息,所以这是我们刚才讲的怎么确保消息到 mq。 好的,我们再来看一下怎么确保我们的消息能够成功的路由到对应的对列,因为你要知道,就算你消息都来 mq, 他只是说消息首先到了这个交换器,但是到了这个交换器之后, 这个消息要路由段对应的对列,如果说你发生了路由失败,一般情况下面啊我们的消息会丢,所以 这个地方我们要开启一个通知,叫做路由失败通知。那么具体怎么处理呢?我们再来看待吗? 好在这个代码中当中我们发到啊,我们点到这个 raptin q 的 template, 这个呢就是消息发送的一个 tempt 类啊,在这个类里面,前面我们已经讲了,这个类里面呢,如果说我们要去设置一个发送失败通知,首先我们要把发送失败通知的开关打开,叫做 set, 叫做 metadare 啊,叫做 set metatory 啊,这个东西我要把它设置为 true, 这个东西设置为 true 呢?是什么意思呢?这个东西叫做开启 失败通知,好,这是第一个,那么设置为 two 之后,紧接着你还要做个事情,因为所有的 m q 里面这种消息的确认啊,他都是走的回调,所以我们还需要去设置 一个回调的函数,叫做 set return call back, 也就是说如果一旦发生了消息的回调失败,这个时候呢,我们可以给他给个方法叫做 return call back 的方法。好,那这个地方就意味着 叫做消息陆游失败,这个时候我们要通知,通知到哪里呢?通知到这个 return call bike 的这一个并里面来, 也就是我定义的一个病的类啊,在这个类里面呢,注意了,有一个方法叫做 return message, 方法,就是一旦发送发生了这种消息路由失败,他就会通知这个方法,在这个方法里面呢,有 message, 有失败的代码对不对?有我们的对应的交换器,有路由键等等之类的啊,所以这里面我我们可以进行一个打印,比如说你如果方法站在这里,那说明他是无法录 路由的消息,这个时候我要考虑重新处理了啊,如果说不考虑处理的话,这个消息他肯定已经丢了,所以呢,这就是如果发生了路由失败,你应该怎么处理的?代码, 好的,我们再回来啊,其实我们还要处理第三个点,就是确保消息能够在消息堆里面进行正确的存储啊,一般来说你要确保消息万无一失, 作为交换器 exchange, 作为对列, ok, 还有了作为对列里面的这个消息,这三者他都需要进行持久化,也就是这三者他都需要保存到磁盘当中,才能确保你 mq, 如果万一发生了 重启发生的荡机,对不对?这个时候我们的消息还可以在 m q 里面进行正确的存储,所以呢,这是第三步,好最后 一步。第四步要确保消息从对列当中进行正确的投递。这个时候一般来说,我们就不让我们的 rap q 走自动提交了,要走一个手动确认,也就是说这个确认呢,要交给消费者来确认,那么具体怎么做呢?我们再来看代码, 首先在这段代码当中,在我的 rapping two 里面的对应的配置里面啊,我定义了一个并,这个并是什么呢?它是一个专门用来手动消费的一个消费者。所以呢,首先 啊,我们这个里面,从这个叫做 simple message listened container 里面,我们拿到一个对应的容器,通过连接工厂拿到对应的容器,一个监听容器, 然后这个监听容器里面呢,我们专门去绑定一个队列,比如说像 q 一好,绑定这个队列之后,我们要设置这个容器,它不是自动提交,所以呢,我们 set acknowledge mode 设置成 menu, 就是一个手动的方式, ok, 然后的话呢,手动方式是不是要交给我们的消费者确认?那给谁确认呢?于是在我们的这个容器里面,我们要设置一个 set message listener, 设置我们具体消费的方法,比如说我这里面定义了一个 resire 的并啊 啊 receiver 的病,在这个 receiver 的病里面,大家可以看到它是实现了一个叫做 china available message listener 的接口,它就是一个专门进行手动消费的一个监听,然后里面有一个方法叫做 on message 方法,就是一旦你监听的这个对着里面有消息,他就会去触发这个 on message 方法进行消费。 在这个 on message 方法里面,大家注意了啊,首先的话呢,我们会拿到对应的 message 消息,还有呢,我们去进行消息通讯的,它对应的信道 china 好,如果这个地方你发生了业务的异常,比如说我们抛出了 exception 怎么办? 那这个时候我们就需要去对这个对应的 channel, 把它设置一个 n a c k, 通过这一个 channel 点 based n a c k 方法设置什么设置我们这个消息了没有消费成功 啊?因为进行消费成功的话是 a c k, 所以说如果正常进行的话呢,我们这个地方甚至 china based a c k 啊,甚至这个消息了已经消费成功了,所以呢,这就是通过手动的方式啊,在你的消费者业务代码里面发生异常的情况,下面我们可以通过手动的方式让 m q 里面进行一个重新派送 啊,当然呢,除了重新派送之外,如果你重新派送失败多次怎么办呢?这个时候一般来说啊, 在 rapinq 里面他也有一个死性消息,就是他会进入一个死性对列里面来进行对列的处理。好,这就是我们刚才所讲的,作为 rapinq 怎么去确保消息做到万无一失不丢失。


那你可以去简单的去类比一下 vip mq 和那个卡福卡他们之间的一个区别有了什么?呃,说真的,我对这个卡福卡不是特别的了解,我们项目里边使用卡福卡就是用的是这个 eik 这样一个场景,没有说 提供太多的这种啊,不保证他可靠的一些机制吧。我我之前了解,但是 reapertambleq 的话我是有系统的一个学习啊,当时我对比的是 reapambaquel, rockamaqu 还有卡不卡?嗯,是这样一个对比的。嗯。然后。呃 rockamaq 我是通过这个家外语言写的。嗯,然后 reachtamaq 的话,它不是加外语言写的就够。呃,好像伊朗吧 这一块的话,家有成就来说,不是说特别的友好,然后卡不卡的话应对这个吞吐量相对来说是最强的。呃, rocky 好像是其次,然后 rabbit 是是第三个。我当时看的总结就是说,如果说我们是一般的这种中小型公司的话,使用 rabbit 又是没有问题的。嗯,当然如果说我们就是整体的技术,对自己整体这个基础基础的一个 技术非常有信心的话,可以使用 rock mq 啊,然后卡不卡的话,我觉得更多的是处处理这些日志方面的一些东西。嗯,然后 rockamq 的话,他给我们提供很多这种去发送到队列的这种方式吗?就是擅出然后掏贝可主题啊,包括点对点这种方式,然后给我们提供这种交换机啊队列, 以及通过这个呃新到的方式去建立连接,包括还给我们提供这种延时队列,就是死音队列这种方式去实现这种延时队列。嗯,然后在正常使用中的话一般都是通过这个套配合去做的啊? ok, 嗯,对,我看他们当中还有一个 ifdymq, 当然这个也知道,但是现在我看的是说比较老嘛,然后比较老现在,而也没有经过一个高病发的一个验证。所以,呃,现在主流的应该就是这个 ok 的或者 rabbit 还有这个卡不卡?嗯, ok。 这边其实不管是哪 没扣吧,多少是要遵循这个 gma 是这个规范。对,然后那个绕贝塔好像是一个 amqp 的一个一个规范吧?嗯嗯, ok。