首页
题库
公司真题
专项练习
面试题库
在线编程
面试
面试经验
AI 模拟面试
简历
求职
学习
基础学习课
实战项目课
求职辅导课
专栏&文章
竞赛
我要招人
发布职位
发布职位、邀约牛人
更多企业解决方案
AI面试、笔试、校招、雇品
HR免费试用AI面试
最新面试提效必备
登录
/
注册
Hpp_
齐齐哈尔大学 Java
发布于浙江
关注
已关注
取消关注
m
@一路向前y:
RabbitMQ面试题
目录什么是 rabbitmq?使用rabbitmq的场景(优点)消息队列有什么缺点?rabbitmq的构造交换机的类型消息怎么路由?消息分发机制如何确保消息正确地发送至RabbitMQ? 如何确保消息接收方消费了消息?消息基于什么传输?如何保证消息不被重复消费(幂等性问题)或重复投递?如何保证消息不丢失,进行可靠性传输?如何保证消息的有序性?如何处理消息堆积情况?几千万条数据在MQ里积压了七八个小时如何保证消息队列的高可用?什么是 rabbitmq?RabbitMQ:是在AMQP(高级消息队列协议)基础上完成的,服务器端用Erlang语言编写,是当前最主流的消息中间件之一使用rabbitmq的场景(优点)流量消峰:订单系统使用消息队列做缓冲,把一秒内下的订单分散成一段时间来处理,这时有些用户可能在下单十几秒后才能收到下单成功的操作应用解耦:比如物流系统因为发生故障,需要几分钟来修复。在这几分钟的时间里,物流系统要处理的内存被缓存在消息队列中,用户的下单操作可以正常完成异步处理消息队列有什么缺点?系统可用性降低:多加了个MQ进来系统复杂度提高:重复消费,处理消息丢失等问题rabbitmq的构造生产者Publisher:生产消息,就是投递消息的一方。消息一般包含两个部分:消息体(payload)和标签(Label)消费者Consumer:消费消息,也就是接收消息的一方。消费者连接到RabbitMQ服务器,并订阅到队列上。消费消息时只消费消息体,丢弃标签。Broker服务节点:表示消息队列服务器实体。一般情况下一个Broker可以看做一个RabbitMQ服务器。Queue:消息队列,用来存放消息。一个消息可投入一个或多个队列,多个消费者可以订阅同一队列,这时队列中的消息会被平摊(轮询)给多个消费者进行处理。Exchange:交换器,接受生产者发送的消息,根据路由键将消息路由到绑定的队列上。Routing Key: 路由关键字,用于指定这个消息的路由规则,需要与交换器类型和绑定键(Binding Key)联合使用才能最终生效。Binding:绑定,通过绑定将交换器和队列关联起来,一般会指定一个BindingKey,通过BindingKey,交换器就知道将消息路由给哪个队列了。Connection :网络连接,比如一个TCP连接,用于连接到具体brokerChannel: 信道,AMQP 命令都是在信道中进行的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接,一个TCP连接可以用多个信道。客户端可以建立多个channel,每个channel表示一个会话任务。Message:消息,由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。Virtual host:虚拟主机,用于逻辑隔离,表示一批独立的交换器、消息队列和相关对象。一个Virtual host可以有若干个Exchange和Queue,同一个Virtual host不能有同名的Exchange或Queue。最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段交换机的类型direct:消息中的路由键(RoutingKey)如果和 Bingding 中的 bindingKey 完全匹配,交换器就将消息发到对应的队列中。是基于完全匹配、单播的模式fanout:把所有发送到fanout交换器的消息路由到所有绑定该交换器的队列中,fanout 类型转发消息是最快的topic:通过模式匹配的方式对消息进行路由,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上routing_key 不能随意写,必须满足一定的要求,它必须是一个单词列表,以点号分隔开,这些单词可以是任意单词,比如说:"stock.usd.nyse"单词列表最多不能超过 255 个字节替换符:(*)可以代替一个单词(#)可以替代零个或多个单词当一个队列绑定键是#,那么这个队列将接收所有数据,就有点像 fanout,如果队列绑定键当中没有#和*出现,那么该队列绑定类型就是 directheaders:不依赖于路由键进行匹配,是根据发送消息内容中的headers属性进行匹配,除此之外 headers 交换器和 direct 交换器完全一致,但性能差很多,目前几乎用不到了消息怎么路由?生产者生产发送消息声明交换器和队列以及相关属性,通过绑定键(binding key)将交换器和队列绑定起来Producer 先连接到 Broker,建立连接 Connection,开启一个信道 channelProducer 发送消息到 Broker,其中包含路由键(routing key)、交换器等信息交换器根据接收到的路由键查找匹配的队列如果找到,将消息存入对应的队列,如果没有找到,会根据生产者的配置丢弃或者退回给生产者关闭信道消费者接收消息Producer 先连接到 Broker,建立连接 Connection,开启一个信道 channel向 Broker 请求消费相应队列中消息,可能会设置响应的回调函数等待 Broker 回应并投递相应队列中的消息,接收消息消费者确认收到的消息,发送ack确认RabbitMQ从队列中删除已经确定的消息关闭信道消息分发机制轮训分发RabbitMQ默认采用的轮训分发,当一个消费者处理速度快一个慢的时候不适用不公平分发通过设置参数 channel.basicQos(1);实现不公平分发策略使得能者多劳预值分发当消息被消费者接收后,但是没有确认,此时这里就存在一个未确认的消息缓冲区,用于存储非被确认的消息,该缓存区的大小是没有限制的通过使用basic.qos方法设置“预取计数”值定义通道上允许的未确认消息的最大数量如何确保消息正确地发送至RabbitMQ? 如何确保消息接收方消费了消息?发送方确认模式:将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的ID。一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一 ID)。如果 RabbitMQ发生内部错误从而导致消息丢失,会发送一条nack(notacknowledged,未确认)消息。发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息接收方确认机制:消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ才能安全地把消息从队列中删除这里并没有用到超时机制,RabbitMQ仅通过Consumer的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ给了Consumer足够长的时间来处理消息。保证数据的最终一致性消息基于什么传输?由于TCP连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ使用信道的方式来传输数据。信道是建立在真实的TCP连接内的虚拟连接,且每条TCP连接上的信道数量没有限制如何保证消息不被重复消费(幂等性问题)或重复投递?数据库唯一主键去重:主键是不能冲突的,重复的数据无法插入引入Redis解决重复消费问题利用Redis,首先系统生成全局唯一的 id,用set操作放入Redis中如订单信息id,消费后存储在Redis中,如果下次再来,先查看Redis中是否存在如果存在,即此消息已经被消费过(后续不做消费处理)如果不存在,即未消费,此时再将此id存入Redis中,进行后续的逻辑操作如何保证消息不丢失,进行可靠性传输?三个角度来分析:生产者丢数据、消息队列丢数据、消费者丢数据生产者丢数据:RabbitMQ提供事务机制(transaction)和确认机制(confirm)两种模式来确保生产者不丢消息事务机制:发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事务就会回滚(channel.txRollback()),如果发送成功则提交事务(channel.txCommit())该方式的缺点是生产者发送消息会同步阻塞等待发送结果是成功还是失败,导致生产者发送消息的吞吐量降下降 channel.txSelect try { // 发送消息 } catch(Exception e){ // 回滚事务 channel.txRollback; //再次重试发送这条消息 .... } //提交事务 channel.txCommit;确认机制:生产环境常用的是confirm模式。生产者将信道 channel 设置成 confirm 模式,一旦 channel 进入 confirm 模式,所有在该信道上发布的消息都将会被指派一个唯一的ID,一旦消息被投递到所有匹配的队列之后,rabbitMQ就会发送一个确认给生产者(包含消息的唯一ID),这样生产者就知道消息已经正确到达目的队列了。如果rabbitMQ没能处理该消息,也会发送一个Nack消息给你,这时就可以进行重试操作Confirm模式最大的好处在于它是异步的,一旦发布消息,生产者就可以在等信道返回确认的同时继续发送下一条消息,当消息最终得到确认之后,生产者便可以通过回调方法来处理该确认消息消息队列丢数据: 处理消息队列丢数据的情况,一般是开启持久化磁盘。持久化配置可以和生产者的 confirm 机制配合使用,在消息持久化磁盘后,再给生产者发送一个Ack信号。这样的话,如果消息持久化磁盘之前,即使 RabbitMQ 挂掉了,生产者也会因为收不到Ack信号而再次重发消息消息持久化:发送消息的时候将 deliveryMode 设置为 2,将消息设置为持久化的,此时 RabbitMQ 就会将消息持久化到磁盘上去队列持久化:创建queue的时候,将queue的持久化标志durable在设置为true,代表是一个持久的队列,这样就可以保证 rabbitmq 持久化 queue 的元数据,但是不会持久化queue里的数据消费者丢数据:消费者丢数据一般是因为采用了自动确认消息模式。该模式下,虽然消息还在处理中,但是消费中者会自动发送一个确认,通知 RabbitMQ 已经收到消息了,这时 RabbitMQ 就会立即将消息删除。这种情况下,如果消费者出现异常而未能处理消息,那就会丢失该消息采用手动确认消息,设置 autoAck = False,等到消息被真正消费之后,再手动发送一个确认信号,即使中途消息没处理完,但是服务器宕机了,那 RabbitMQ 就收不到发的ack,然后 RabbitMQ 就会将这条消息重新分配给其他的消费者去处理但是 RabbitMQ 并没有使用超时机制,RabbitMQ 仅通过与消费者的连接来确认是否需要重新发送消息,也就是说,只要连接不中断,RabbitMQ 会给消费者足够长的时间来处理消息需要考虑的情况:如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ 会认为消息没有被消费,然后重新分发给下一个订阅的消费者,所以存在消息重复消费的隐患如果消费者接收到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙,将不会给该消费者分发更多的消息如何保证消息的有序性?方法一:拆分queue,使得一个queue只对应一个消费者由于MQ一般都能保证内部队列是先进先出的,所以把需要保持先后顺序的一组消息使用某种算法都分配到同一个消息队列中。然后只用一个消费者单线程去消费该队列,这样就能保证消费者是按照顺序进行消费的了但是消费者的吞吐量会出现瓶颈。如果多个消费者同时消费一个队列,还是可能会出现顺序错乱的情况,这就相当于是多线程消费了方法二:对于多线程的消费同一个队列的情况,可以使用重试机制:比如有一个微博业务场景的操作,发微博、写评论、删除微博,这三个异步操作,如果一个消费者先执行了写评论的操作,但是这时微博都还没发,写评论一定是失败的,等一段时间。等另一个消费者,先执行发微博的操作后,再执行,就可以成功如何处理消息堆积情况?几千万条数据在MQ里积压了七八个小时出现该问题的原因:消息堆积往往是生产者的生产速度与消费者的消费速度不匹配导致的。有可能就是消费者消费能力弱,渐渐地消息就积压了,也有可能是因为消息消费失败反复复重试造成的,也有可能是消费端出了问题,导致不消费了或者消费极其慢临时扩容,快速处理积压的消息:先修复 consumer 的问题,确保其恢复消费速度,然后将现有的 consumer 都停掉;临时创建原先 N 倍数量的 queue ,然后写一个临时分发数据的消费者程序,将该程序部署上去消费队列中积压的数据,消费之后不做任何耗时处理,直接均匀轮询写入临时建立好的 N 倍数量的 queue 中;接着,临时征用 N 倍的机器来部署 consumer,每个 consumer 消费一个临时 queue 的数据等快速消费完积压数据之后,恢复原先部署架构 ,重新用原先的 consumer 机器消费消息。这种做法相当于临时将 queue 资源和 consumer 资源扩大 N 倍,以正常 N 倍速度消费恢复队列中丢失的数据:如果使用的是 rabbitMQ,并且设置了过期时间,消息在 queue 里积压超过一定的时间会被 rabbitmq 清理掉,导致数据丢失,这种情况下,实际上队列中没有什么消息挤压,而是丢了大量的消息,所以就不能说增加 consumer 消费积压的数据了这种情况可以采取 “批量重导” 的方案来进行解决。在流量低峰期,写一个程序,手动去查询丢失的那部分数据,然后将消息重新发送到mq里面,把丢失的数据重新补回来MQ长时间未处理导致MQ写满的情况如何处理:如果消息积压在MQ里,并且长时间都没处理掉,导致MQ都快写满了,这种情况肯定是临时扩容方案执行太慢这种时候只好采用 “丢弃+批量重导” 的方式来解决了。首先,临时写个程序,连接到mq里面消费数据,消费一个丢弃一个,快速消费掉积压的消息,降低MQ的压力,然后在流量低峰期时去手动查询重导丢失的这部分数据如何保证消息队列的高可用?RabbitMQ 是基于主从(非分布式)做高可用性的,RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式单机模式:一般没人生产用单机模式普通集群模式:就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。我们创建的 queue,只会放在其中一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据(元数据是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。消费的时候,如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来优点:普通集群模式主要用于提高系统的吞吐量,可以通过添加更加的节点来线性的扩展消息队列的吞吐量,就是说让集群中多个节点来服务某个 queue 的读写操作缺点:无高可用性,queue所在的节点宕机了,其他实例就无法从那个实例拉取数据;RabbitMQ 内部也会产生大量的数据传输镜像集群模式:
点赞 5
评论 1
全部评论
推荐
最新
楼层
暂无评论,快来抢首评~
相关推荐
昨天 16:40
门头沟学院 活动运营
没有人关心你在学校有多牛逼
hr只关心你的学校有多牛逼,你是什么部长,做了什么活动,和找工作关系一点都不大,今天看实习生简历,有人把自己王者排名都写到简历了,找工作真是长点心吧.......... 你多高多瘦没人在意,但长得好看确实有人在意简历上有一个样貌端庄的照片很重要!学校好的简历上优先写学校,然后是实习、项目这个顺序,没有实习就写项目、然后写点个人评价,个人证书等等,简历优先匹配岗位去写!
东东鱼:
王者百星能加工资吗
点赞
评论
收藏
分享
05-27 17:00
已编辑
云南民族大学 HRBP
大学生别在无效竞争里浪费时间
最近常听到有同学纠结:"要不要花三个月备赛拿个 ' 互联网 +' 铜奖?""加入这个科研小组,对保研有帮助吗?"先泼一盆冷水:如果你既不打算走学术保研路径,也不想用竞赛经历 "包装" 简历,那么大部分校园竞赛、科研项目(除非与目标行业强相关),本质上都是 "象牙塔里的自我感动"。一、为什么说 "竞赛 / 项目无用论"?(特指就业导向)企业招聘不看 "学生思维" 的努力HR 筛选简历时,更关注:✅ 有没有行业相关实习经历(如快消行业看市场部实习、互联网看大厂实习经验) 不关心 ...
P城我有四套房:
大二开始实习不是 “卷”,是 “用时间换试错空间”。等大四再投简历时你会发现:别人已经带着 “3 段大厂实习 + 1 个独立项目” 和你竞争,而你的简历还停留在 “校级优秀团员 + 学生会干事”—— 有些差距,不是靠 “考研高分” 就能弥补的。
点赞
评论
收藏
分享
04-27 08:59
常州大学 Java
这是来招人的还是来恶心人的😅
牛客139242382号:
《两门以上汇编语言》
点赞
评论
收藏
分享
05-21 18:40
湖南工程学院 Java
求大佬指点
比例好低啊,就两个面试
点赞
评论
收藏
分享
05-26 23:28
中南大学 Java
论校招生怎么成长为一名优秀架构师
很多同学都想成为架构师,那么校招生怎么成长为一名优秀架构师呢?别问我,我也不知道。我打算边工作边跟组里老b登学,因为我组里大部分都是架构师老登。那么有没有一种通用的方法论或者说详细教程可以让所有后端开发校招生成长为一名架构师呢?我觉得没有,因为每个人所在的公司不同,部门不同,领导不同,业务不同,际遇不同,决定着每个人的发展道路一定是不一样的。但是前辈的经验包还是十分有必要吃的,我每次技术面最后都会反问面试官怎么成为一名架构师,他们的回答都不一样,这刚好印证了我刚才说的每个人的发展道路不一样。在这里我把他们的观点原封不动、不论对错的分享出来,也算是对我这么多场面试经历的总结了。下面是不同公司不同...
投递快手等公司10个岗位 >
秋招最大的收获是什么?
牛客创作赏金赛
点赞
评论
收藏
分享
评论
点赞成功,聊一聊 >
点赞
收藏
分享
评论
提到的真题
返回内容
全站热榜
更多
1
...
我的校园恋爱正式结束了
1.3W
2
...
极限春招小结
1.1W
字节暑期补捞
热聊中
3
...
本科四年,我决定在即将毕业时转行
1.1W
4
...
这次是真的告别了!
1.0W
5
...
找工作找到厌倦了,晒一下毕业照吧!
8786
6
...
上午拍毕业照,下午拍结婚照!牛友祝福我们吧!
8359
7
...
极限春招一个月总结
7988
8
...
从后端的角度聊一聊:2728届想要搞开发的同学现在最应该干什么?
7792
9
...
第一次给了美团
7284
10
...
毕业照和春招结束代表着我的学生时代落幕了
6475
创作者周榜
更多
正在热议
更多
#
写给毕业5年后的自己
#
3806次浏览
64人参与
#
好好告别我的学生时代
#
39767次浏览
786人参与
#
华泰证券Fintech星战营
#
167914次浏览
190人参与
#
职场捅娄子大赛
#
316760次浏览
3247人参与
#
晒一下我的毕业照
#
30355次浏览
320人参与
#
华为求职进展汇总
#
4642009次浏览
28243人参与
#
如何缓解求职过程中的焦虑?
#
6998次浏览
93人参与
#
海信求职进展汇总
#
64728次浏览
356人参与
#
如果今天是你的last day,你会怎么度过?
#
22514次浏览
197人参与
#
记录实习开销
#
23802次浏览
175人参与
#
晒晒我司的端午福利
#
14743次浏览
99人参与
#
HR问:你期望的薪资是多少?如何回答
#
39850次浏览
524人参与
#
上班苦还是上学苦呢?
#
222600次浏览
1327人参与
#
当下环境,你会继续卷互联网,还是看其他行业机会
#
108101次浏览
780人参与
#
毕业季等于分手季吗
#
11383次浏览
108人参与
#
如果中了500万,你会离职吗?
#
81885次浏览
649人参与
#
视觉/交互/设计百问百答
#
43097次浏览
427人参与
#
实习/项目/竞赛奖项,哪个对找工作更重要?
#
82763次浏览
1108人参与
#
参加完秋招的机械人,还参加春招吗?
#
47712次浏览
544人参与
#
工作两年想退休了
#
119763次浏览
1116人参与
#
简历无回复,你会继续海投还是优化再投?
#
70161次浏览
699人参与
牛客网
牛客企业服务