精华内容
下载资源
问答
  • 项目中为什么使用消息队列 解耦,降低各个系统间的耦合度,使...常见消息队列产品 activemq、rabbitmq、rocketmq、kafka 四种消息队列各有优缺点,项目中根据实际情况选择 建议: 中小型公司选用rabbitmq(社区活跃

    项目中为什么使用消息队列

    1. 解耦,降低各个系统间的耦合度,使项目易于维护。
      将系统产生的消息发送给MQ,不用维护系间的调用,而是让有需要的系统自己来消费消息。
    2. 异步(提速),提高系统响应的速度(200ms为用户无感知时间)
    3. 削峰,抗住大量请求涌向数据库

    消息队列的缺点

    • 系统可用性降低
    • 系统复杂度提高
    • 存在数据一致性问题

    常见的消息队列产品

    activemq、rabbitmq、rocketmq、kafka
    四种消息队列各有优缺点,项目中根据实际情况选择

    建议: 中小型公司选用rabbitmq(社区活跃),大型公司选择rocketmq、大数据方向选择kafka

    展开全文
  • 消息队列的4个常见应用场景分类:云服务资讯编辑:互联网观察浏览量:1932020-12-25 14:07:16几十年前,消息队列开始兴起,它用于连接大型机和服务器应用程序,并逐渐在企业的服务总线与事件总线设计模式、应用间的...

    消息队列的4个常见应用场景

    分类:云服务资讯

    编辑:互联网观察

    浏览量:193

    2020-12-25 14:07:16

    几十年前,消息队列开始兴起,它用于连接大型机和服务器应用程序,并逐渐在企业的服务总线与事件总线设计模式、应用间的路由和数据迁移中发挥至关重要的作用。

    2020年处于移动互联网的下半场,各种技术层出不穷,虽然数据也在爆发式增长,但是高并发、高吞吐已经不再是首要的痛点,稳定、可靠才是王道。

    本文作为一篇消息队列入门级介绍,帮助大家对消息队列有一个大致的了解,并对对时下流行的消息队列组件进行了简单的比较。

    一、为什么需要消息队列?

    消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。使用较多的消息队列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ。

    由于在高并发环境下,同步请求来不及处理,请求往往会发生阻塞。大量的请求到达访问数据库,导致行锁表锁,最后请求线程会堆积过多,从而触发 too many connection错误,引发雪崩效应。我们使用消息队列,通过异步处理请求,从而缓解系统的压力。

    二、消息队列应用场景

    以下介绍消息队列在实际应用中常用的使用场景:异步处理,应用解耦,流量削锋和消息通讯四个场景。

    1、异步处理

    场景说明:用户注册后,需要发注册邮件和注册短信。传统的做法有两种:串行的方式和并行方式。

    串行方式:将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户。

    并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。

    假设三个业务节点每个使用50毫秒钟,不考虑网络等其他开销,则串行方式的时间是150毫秒,并行的时间可能是100毫秒。

    因为CPU在单位时间内处理的请求数是一定的,假设CPU1秒内吞吐量是100次。则串行方式1秒内CPU可处理的请求量是7次(1000/150)。并行方式处理的请求量是10次(1000/100)。

    小结:如以上案例描述,传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈。如何解决这个问题呢?

    引入消息队列,将不是必须的业务逻辑,异步处理。

    按照以上约定,用户的响应时间相当于是注册信息写入数据库的时间,也就是50毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20QPS。比串行提高了3倍,比并行提高了两倍!

    2、应用解耦

    场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。

    传统模式的缺点:假如库存系统无法访问,则订单减库存将失败,从而导致订单失败,订单系统与库存系统耦合。

    如何解决以上问题呢?引入应用消息队列后的方案:

    订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功

    库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作

    假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦。

    3、流量削锋

    流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛!

    应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。

    可以控制活动的人数,可以缓解短时间内高流量压垮应用。

    用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。

    秒杀业务根据消息队列中的请求信息,再做后续处理。

    4、消息通讯

    消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。

    客户端A和客户端B使用同一队列,进行消息通讯。

    客户端A,客户端B,客户端N订阅同一主题,进行消息发布和接收。实现类似聊天室效果。

    新网消息队列RabbitMQ,是一款支持持久化消息队列的消息中间件。通过创建集群的方式来实现RabbitMQ以及所依赖的服务的部署,完全兼容RabbitMQ开源生态以及多语言客户端,为用户提供快速创建、方便管理的消息中间件。支持多种模式,满足不同使用场景,包括简单队列模式、work模式、发布/订阅模式、路由模式、topic模式等:http://www.xinnet.com/cs/rabbitmq.html

    声明:免责声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,也不承认相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,请发

    送邮件至:operations@xinnet.com进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。本站原创内容未经允许不得转载,或转载时

    需注明出处:新网idc知识百科

    展开全文
  • 天天说队列, 项目请求...消息队列应用场景1.比如你的服务器一秒能处理100个订单,但秒杀活动1秒进来1000个订单,持续10秒,在后端能力无法增加的情况下,你可以用消息队列将总共10000个请求压在队列里,后台consu...

    天天说队列, 项目请求数据不能及时处理时,就一言不合通过队列啊, 心中那个是妈卖批,那么到底什么队列呢,队列有到底运用于哪些运用场景呢;

    先说说应用场景吧, 不知道有啥作用,看多了含义,原理什么的还是头疼;

    消息队列应用场景

    1.比如你的服务器一秒能处理100个订单,但秒杀活动1秒进来1000个订单,持续10秒,在后端能力无法增加的情况下,你可以用消息队列将总共10000个请求压在队列里,后台consumer按原有能力处理,100秒后处理完所有请求(而不是直接宕机丢失订单数据)

    使用消息队列能够使关键组件顶住增长的访问压力,而不是因为超出负荷的请求而完全崩溃 , 就是防止雪崩。某一时刻数据量突然增大,起到一个缓冲。

    2.一般都是异步的,不要求立即响应。打个比喻,你同时只能做一件事,但是你有一个ToDoList,每做完一个,在ToDoList中划掉一个,有新的分给你的任务,就放到ToDoList后面,这个ToDoList差不多就是一个队列了,队列就是一种数据结构,减轻的不止是数据库的压力。

    3.可用于一些不及时的操作,耗时的操作,比如发送邮件、图片处理等等。

    就是将比较耗时而且不需要即时(同步)返回结果的操作作为消息放入消息队列。同时由于使用了消息队列,只要保证消息格式不变,消息的发送方和接收方并不需要彼此联系,也不需要受对方的影响,即解耦和。

    4.项目功能软件的正常使用中,并不需要去刻意的使用消息队列处理,而是当出现性能瓶颈时采用,否则盲目的使用消息队列 , 增加维护和开发的成本,反而影响开发进度而得不偿失。

    消息队列种类及特点:

    rabbitMQ稳定,可靠,数据一致,支持多协议,有消息确认,性能一般,基于erlang语言,二次开发困难.

    kafka高吞吐,高性能,快速持久化,无消息确认,无消息遗漏,可能会有有重复消息,依赖于zookeeper,成本高.

    ZeroMQ灵活快速,不支持持久化,需要大量编码来实现稳定可靠.

    ActiveMQ不够灵活轻巧,对队列较多情况支持不好.

    rocketMQ性能好,高吞吐,高可用性,支持大规模分布式.

    ZeroMQ小而美,RabbitMQ大而稳,Kakfa和RocketMQ快而强劲。

    转载自https://blog.csdn.net/qq_43843725/article/details/95113436

    展开全文
  • RabbitMQ消息队列常见面试题总结

    万次阅读 多人点赞 2021-03-22 02:46:39
    RabbitMQ消息队列常见面试题总结; 1、什么是消息队列?消息队列的优缺点? 2、Kafka、ActiveMQ、RabbitMQ、RocketMQ的区别? 3、如何保证消息不被重复消费? 4、如何保证消息不丢失,进行可靠性传输? 5、如何保证...

    1、什么是消息队列:

    1.1、消息队列的优点:

    (1)解耦:将系统按照不同的业务功能拆分出来,消息生产者只管把消息发布到 MQ 中而不用管谁来取,消息消费者只管从 MQ 中取消息而不管是谁发布的。消息生产者和消费者都不知道对方的存在;

    (2)异步:主流程只需要完成业务的核心功能;对于业务非核心功能,将消息放入到消息队列之中进行异步处理,减少请求的等待,提高系统的总体性能;

    (3)削峰/限流:将所有请求都写到消息队列中,消费服务器按照自身能够处理的请求数从队列中拿到请求,防止请求并发过高将系统搞崩溃;

    1.2、消息队列的缺点:

    (1)系统的可用性降低:系统引用的外部依赖越多,越容易挂掉,如果MQ 服务器挂掉,那么可能会导致整套系统崩溃。这时就要考虑如何保证消息队列的高可用了

    (2)系统复杂度提高:加入消息队列之后,需要保证消息没有重复消费、如何处理消息丢失的情况、如何保证消息传递的有序性等问题;

    (3)数据一致性问题:A 系统处理完了直接返回成功了,使用者都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,就会导致数据不一致了

    1.3、Kafka、ActiveMQ、RabbitMQ、RocketMQ 消息队列的选型:

    每种MQ没有绝对的好坏,主要依据使用场景,扬长避短,利用其优势,规避其劣势。

    (1)中小型软件公司,技术实力较为一般,建议选RabbitMQ:一方面,erlang语言天生具备高并发的特性,而且管理界面用起来十分方便。代码是开源的,而且社区十分活跃,可以解决开发过程中遇到的bug,这点对于中小型公司来说十分重要。

    • 不考虑 rocketmq 的原因是,rocketmq是阿里出品,如果阿里放弃维护rocketmq,中小型公司一般抽不出人来进行rocketmq的定制化开发,因此不推荐。
    • 不考虑 kafka 的原因是:中小型软件公司不如互联网公司,数据量没那么大,选消息中间件应首选功能比较完备的,所以kafka排除

    (2)大型软件公司:根据具体使用场景在rocketMq和kafka之间二选一。

    一方面,大型软件公司,具备足够的资金搭建分布式环境,也具备足够大的数据量。针对rocketMQ,大型软件公司有能力对rocketMQ进行定制化开发。至于kafka,如果是大数据领域的实时计算、日志采集功能,肯定是首选kafka了。

    2、RabbitMQ的构造:

    RabbitMQ 是 AMQP 协议的一个开源实现,所以其内部实际上也是 AMQP 中的基本概念:

    RabbitMQ 内部结构

    • (1)生产者Publisher:生产消息,就是投递消息的一方。消息一般包含两个部分:消息体(payload)和标签(Label)
    • (2)消费者Consumer:消费消息,也就是接收消息的一方。消费者连接到RabbitMQ服务器,并订阅到队列上。消费消息时只消费消息体,丢弃标签。
    • (3)Broker服务节点:表示消息队列服务器实体。一般情况下一个Broker可以看做一个RabbitMQ服务器。
    • (4)Queue:消息队列,用来存放消息。一个消息可投入一个或多个队列,多个消费者可以订阅同一队列,这时队列中的消息会被平摊(轮询)给多个消费者进行处理。
    • (5)Exchange:交换器,接受生产者发送的消息,根据路由键将消息路由到绑定的队列上。
    • (6)Routing Key: 路由关键字,用于指定这个消息的路由规则,需要与交换器类型和绑定键(Binding Key)联合使用才能最终生效。
    • (7)Binding:绑定,通过绑定将交换器和队列关联起来,一般会指定一个BindingKey,通过BindingKey,交换器就知道将消息路由给哪个队列了。
    • (8)Connection :网络连接,比如一个TCP连接,用于连接到具体broker
    • (9)Channel: 信道,AMQP 命令都是在信道中进行的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接,一个TCP连接可以用多个信道。客户端可以建立多个channel,每个channel表示一个会话任务。
    • (10)Message:消息,由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。
    • (11)Virtual host:虚拟主机,用于逻辑隔离,表示一批独立的交换器、消息队列和相关对象。一个Virtual host可以有若干个Exchange和Queue,同一个Virtual host不能有同名的Exchange或Queue。最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段

    3、Exchange交换器的类型:

    Exchange分发消息时根据类型的不同分发策略有区别,目前共四种类型:direct、fanout、topic、headers

    (1)direct:消息中的路由键(RoutingKey)如果和 Bingding 中的 bindingKey 完全匹配,交换器就将消息发到对应的队列中。是基于完全匹配、单播的模式。

    (2)fanout:把所有发送到fanout交换器的消息路由到所有绑定该交换器的队列中,fanout 类型转发消息是最快的。

    (3)topic:通过模式匹配的方式对消息进行路由,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。

    匹配规则:

    • ① RoutingKey 和 BindingKey 为一个 点号 '.' 分隔的字符串。 比如: java.xiaoka.show
    • ② BindingKey可使用 * 和 # 用于做模糊匹配:*匹配一个单词,#匹配多个或者0个单词

    (4)headers:不依赖于路由键进行匹配,是根据发送消息内容中的headers属性进行匹配,除此之外 headers 交换器和 direct 交换器完全一致,但性能差很多,目前几乎用不到了

    4、生产者消息的过程:

    • (1)Producer 先连接到 Broker,建立连接 Connection,开启一个信道 channel
    • (2)Producer 声明一个交换器并设置好相关属性
    • (3)Producer 声明一个队列并设置好相关属性
    • (4)Producer 通过绑定键将交换器和队列绑定起来
    • (5)Producer 发送消息到 Broker,其中包含路由键、交换器等信息
    • (6)交换器根据接收到的路由键查找匹配的队列
    • (7)如果找到,将消息存入对应的队列,如果没有找到,会根据生产者的配置丢弃或者退回给生产者。
    • (8)关闭信道

    5、消费者接收消息过程:

    • (1)Producer 先连接到 Broker,建立连接 Connection,开启一个信道 channel
    • (2)向 Broker 请求消费相应队列中消息,可能会设置响应的回调函数。
    • (3)等待 Broker 回应并投递相应队列中的消息,接收消息。
    • (4)消费者确认收到的消息,ack。
    • (5)RabbitMQ从队列中删除已经确定的消息。
    • (6)关闭信道

    6、如何保证消息不被重复消费?

    正常情况下,消费者在消费消息后,会给消息队列发送一个确认,消息队列接收后就知道消息已经被成功消费了,然后就从队列中删除该消息,也就不会将该消息再发送给其他消费者了。不同消息队列发出的确认消息形式不同,RabbitMQ是通过发送一个ACK确认消息。但是因为网络故障,消费者发出的确认并没有传到消息队列,导致消息队列不知道该消息已经被消费,然后就再次消息发送给了其他消费者,从而造成重复消费的情况。

    重复消费问题的解决思路是:保证消息的唯一性,即使多次传输,也不让消息的多次消费带来影响,也就是保证消息等幂性;幂等性指一个操作执行任意多次所产生的影响均与一次执行的影响相同。具体解决方案如下:

    (1)改造业务逻辑,使得在重复消费时也不影响最终的结果。例如对SQL语句: update t1 set money = 150 where id = 1 and money = 100; 做了个前置条件判断,即 money = 100 的情况下才会做更新,更通用的是做个 version 即版本号控制,对比消息中的版本号和数据库中的版本号。

    (2)基于数据库的的唯一主键进行约束。消费完消息之后,到数据库中做一个 insert 操作,如果出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。

    (3)通过记录关键的key,当重复消息过来时,先判断下这个key是否已经被处理过了,如果没处理再进行下一步。

    • ① 通过数据库:比如处理订单时,记录订单ID,在消费前,去数据库中进行查询该记录是否存在,如果存在则直接返回。
    • ② 使用全局唯一ID,再配合第三组主键做消费记录,比如使用 redis 的 set 结构,生产者发送消息时给消息分配一个全局ID,在每次消费者开始消费前,先去redis中查询有没有消费记录,如果消费过则不进行处理,如果没消费过,则进行处理,消费完之后,就将这个ID以k-v的形式存入redis中(过期时间根据具体情况设置)。

    7、如何保证消息不丢失,进行可靠性传输?

    对于消息的可靠性传输,每种MQ都要从三个角度来分析:生产者丢数据、消息队列丢数据、消费者丢数据。以RabbitMQ为例:

    7.1、生产者丢数据:

    RabbitMQ提供事务机制(transaction)和确认机制(confirm)两种模式来确保生产者不丢消息。

    (1)事务机制:

            发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事务就会回滚(channel.txRollback()),如果发送成功则提交事务(channel.txCommit())

            该方式的缺点是生产者发送消息会同步阻塞等待发送结果是成功还是失败,导致生产者发送消息的吞吐量降下降。

        // 开启事务
        channel.txSelect
        try {
            // 发送消息
        } catch(Exception e){
            // 回滚事务
            channel.txRollback;
            //再次重试发送这条消息
            ....
        }      
        //提交事务
        channel.txCommit;

    (2)确认机制:

            生产环境常用的是confirm模式。生产者将信道 channel 设置成 confirm 模式,一旦 channel 进入 confirm 模式,所有在该信道上发布的消息都将会被指派一个唯一的ID,一旦消息被投递到所有匹配的队列之后,rabbitMQ就会发送一个确认给生产者(包含消息的唯一ID),这样生产者就知道消息已经正确到达目的队列了。如果rabbitMQ没能处理该消息,也会发送一个Nack消息给你,这时就可以进行重试操作。

            Confirm模式最大的好处在于它是异步的,一旦发布消息,生产者就可以在等信道返回确认的同时继续发送下一条消息,当消息最终得到确认之后,生产者便可以通过回调方法来处理该确认消息。

    处理Ack和Nack的代码如下所示:

    channel.addConfirmListener(new ConfirmListener() {  
        @Override  
        public void handleNack(long deliveryTag, boolean multiple) throws IOException {  
            System.out.println("nack: deliveryTag = "+deliveryTag+" multiple: "+multiple);  
        }  
        @Override  
        public void handleAck(long deliveryTag, boolean multiple) throws IOException {  
            System.out.println("ack: deliveryTag = "+deliveryTag+" multiple: "+multiple);  
        }  
    }); 

    7.2、消息队列丢数据:

            处理消息队列丢数据的情况,一般是开启持久化磁盘。持久化配置可以和生产者的 confirm 机制配合使用,在消息持久化磁盘后,再给生产者发送一个Ack信号。这样的话,如果消息持久化磁盘之前,即使 RabbitMQ 挂掉了,生产者也会因为收不到Ack信号而再次重发消息。

    持久化设置如下(必须同时设置以下 2 个配置):

    • (1)创建queue的时候,将queue的持久化标志durable在设置为true,代表是一个持久的队列,这样就可以保证 rabbitmq 持久化 queue 的元数据,但是不会持久化queue里的数据;
    • (2)发送消息的时候将 deliveryMode 设置为 2,将消息设置为持久化的,此时 RabbitMQ 就会将消息持久化到磁盘上去。

            这样设置以后,RabbitMQ 就算挂了,重启后也能恢复数据。在消息还没有持久化到硬盘时,可能服务已经死掉,这种情况可以通过引入镜像队列,但也不能保证消息百分百不丢失(整个集群都挂掉)

    7.3、消费者丢数据:

            消费者丢数据一般是因为采用了自动确认消息模式。该模式下,虽然消息还在处理中,但是消费中者会自动发送一个确认,通知 RabbitMQ 已经收到消息了,这时 RabbitMQ 就会立即将消息删除。这种情况下,如果消费者出现异常而未能处理消息,那就会丢失该消息。

            解决方案就是采用手动确认消息,设置 autoAck = False,等到消息被真正消费之后,再手动发送一个确认信号,即使中途消息没处理完,但是服务器宕机了,那 RabbitMQ 就收不到发的ack,然后 RabbitMQ 就会将这条消息重新分配给其他的消费者去处理。

            但是 RabbitMQ 并没有使用超时机制,RabbitMQ 仅通过与消费者的连接来确认是否需要重新发送消息,也就是说,只要连接不中断,RabbitMQ 会给消费者足够长的时间来处理消息。另外,采用手动确认消息的方式,我们也需要考虑一下几种特殊情况:

    • 如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ 会认为消息没有被消费,然后重新分发给下一个订阅的消费者,所以存在消息重复消费的隐患
    • 如果消费者接收到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙,将不会给该消费者分发更多的消息

    需要注意的点:

    1、消息可靠性增强了,性能就下降了,因为写磁盘比写 RAM 慢的多,两者的吞吐量可能有 10 倍的差距。所以,是否要对消息进行持久化,需要综合考虑业务场景、性能需要,以及可能遇到的问题。若想达到单RabbitMQ服务器 10W 条/秒以上的消息吞吐量,则要么使用其他的方式来确保消息的可靠传输,要么使用非常快速的存储系统以支持全持久化,例如使用 SSD。或者仅对关键消息作持久化处理,且应该保证关键消息的量不会导致性能瓶颈。

    2、当设置 autoAck = False 时,如果忘记手动 ack,那么将会导致大量任务都处于 Unacked 状态,造成队列堆积,直至消费者断开才会重新回到队列。解决方法是及时 ack,确保异常时 ack 或者拒绝消息。

    3、启用消息拒绝或者发送 nack 后导致死循环的问题:如果在消息处理异常时,直接拒绝消息,消息会重新进入队列。这时候如果消息再次被处理时又被拒绝 。这样就会形成死循环。

    8、如何保证消息的有序性?

            针对保证消息有序性的问题,解决方法就是保证生产者入队的顺序是有序的,出队后的顺序消费则交给消费者去保证。

    (1)方法一:拆分queue,使得一个queue只对应一个消费者。由于MQ一般都能保证内部队列是先进先出的,所以把需要保持先后顺序的一组消息使用某种算法都分配到同一个消息队列中。然后只用一个消费者单线程去消费该队列,这样就能保证消费者是按照顺序进行消费的了。但是消费者的吞吐量会出现瓶颈。如果多个消费者同时消费一个队列,还是可能会出现顺序错乱的情况,这就相当于是多线程消费了

    (2)方法二:对于多线程的消费同一个队列的情况,可以使用重试机制:比如有一个微博业务场景的操作,发微博、写评论、删除微博,这三个异步操作。如果一个消费者先执行了写评论的操作,但是这时微博都还没发,写评论一定是失败的,等一段时间。等另一个消费者,先执行发微博的操作后,再执行,就可以成功。

    9、如何处理消息堆积情况?

    场景题:几千万条数据在MQ里积压了七八个小时。

    9.1、出现该问题的原因:

    消息堆积往往是生产者的生产速度与消费者的消费速度不匹配导致的。有可能就是消费者消费能力弱,渐渐地消息就积压了,也有可能是因为消息消费失败反复复重试造成的,也有可能是消费端出了问题,导致不消费了或者消费极其慢。比如,消费端每次消费之后要写mysql,结果mysql挂了,消费端hang住了不动了,或者消费者本地依赖的一个东西挂了,导致消费者挂了。

    所以如果是 bug 则处理 bug;如果是因为本身消费能力较弱,则优化消费逻辑,比如优化前是一条一条消息消费处理的,那么就可以批量处理进行优化。

    9.2、临时扩容,快速处理积压的消息:

    (1)先修复 consumer 的问题,确保其恢复消费速度,然后将现有的 consumer 都停掉;

    (2)临时创建原先 N 倍数量的 queue ,然后写一个临时分发数据的消费者程序,将该程序部署上去消费队列中积压的数据,消费之后不做任何耗时处理,直接均匀轮询写入临时建立好的 N 倍数量的 queue 中;

    (3)接着,临时征用 N 倍的机器来部署 consumer,每个 consumer 消费一个临时 queue 的数据

    (4)等快速消费完积压数据之后,恢复原先部署架构 ,重新用原先的 consumer 机器消费消息。

    这种做法相当于临时将 queue 资源和 consumer 资源扩大 N 倍,以正常 N 倍速度消费。

    9.3、恢复队列中丢失的数据:

    如果使用的是 rabbitMQ,并且设置了过期时间,消息在 queue 里积压超过一定的时间会被 rabbitmq 清理掉,导致数据丢失。这种情况下,实际上队列中没有什么消息挤压,而是丢了大量的消息。所以就不能说增加 consumer 消费积压的数据了,这种情况可以采取 “批量重导” 的方案来进行解决。在流量低峰期,写一个程序,手动去查询丢失的那部分数据,然后将消息重新发送到mq里面,把丢失的数据重新补回来。

    9.4、MQ长时间未处理导致MQ写满的情况如何处理:

    如果消息积压在MQ里,并且长时间都没处理掉,导致MQ都快写满了,这种情况肯定是临时扩容方案执行太慢,这种时候只好采用 “丢弃+批量重导” 的方式来解决了。首先,临时写个程序,连接到mq里面消费数据,消费一个丢弃一个,快速消费掉积压的消息,降低MQ的压力,然后在流量低峰期时去手动查询重导丢失的这部分数据。

    10、如何保证消息队列的高可用?

    RabbitMQ 是基于主从(非分布式)做高可用性的,RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式

    10.1、单机模式:一般没人生产用单机模式

    10.2、普通集群模式:

    就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。我们创建的 queue,只会放在其中一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据(元数据是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。消费的时候,如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来。

    (1)优点:普通集群模式主要用于提高系统的吞吐量,可以通过添加更加的节点来线性的扩展消息队列的吞吐量,就是说让集群中多个节点来服务某个 queue 的读写操作

    (2)缺点:无高可用性,queue所在的节点宕机了,其他实例就无法从那个实例拉取数据;RabbitMQ 内部也会产生大量的数据传输。

    10.3、镜像集群模式:

    RabbitMQ 真正的高可用模式。镜像集群模式下,队列的元数据和消息会存在于多个实例上,每次写消息到 queue 时,会自动将消息同步到各个实例的 queue ,也就是说每个 RabbitMQ 节点都有这个 queue 的完整镜像,包含 queue 的全部数据。任何一个机器宕机了,其它机器节点还包含了这个 queue 的完整数据,其他 consumer 都可以到其它节点上去消费数据。

    配置镜像队列的集群都包含一个主节点master和若干个从节点slave,slave会准确地按照master执行命令的顺序进行动作,故slave与master上维护的状态应该是相同的。如果master由于某种原因失效,那么按照slave加入的时间排序,"资历最老"的slave会被提升为新的master。

    除发送消息外的所有动作都只会向master发送,然后再由master将命令执行的结果广播给各个slave。如果消费者与slave建立连接并进行订阅消费,其实质上都是从master上获取消息,只不过看似是从slave上消费而已。比如消费者与slave建立了TCP连接之后执行一个Basic.Get的操作,那么首先是由slave将Basic.Get请求发往master,再由master准备好数据返回给slave,最后由slave投递给消费者。

    (1)缺点:

    ① 性能开销大,消息需要同步到所有机器上,导致网络带宽压力和消耗很重

    ② 非分布式,没有扩展性,如果 queue 的数据量大到这个机器上的容量无法容纳了,此时该方案就会出现问题了

    (2)如何开启镜像集群模式呢?

    在RabbitMQ 的管理控制台Admin页面下,新增一个镜像集群模式的策略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。

    11、其他:

    (1)交换器无法根据自身类型和路由键找到符合条件队列时,有哪些处理方式:设置mandatory = true,代表返回消息给生产者;设置mandatory = false,代表直接丢弃

    (2)消费者得到消息队列中的数据的方式:push 和 pull

    (3)消息基于什么传输:由于 TCP 连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。所以RabbitMQ 使用信道 channel 的方式来传输数据,信道是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制。

    (4)死信队列DLX:

            DLX也是一个正常的Exchange,和一般的Exchange没有任何区别。能在任何的队列上被指定,实际上就是设置某个队列的属性。当这个队列出现死信(dead message,就是没有任何消费者消费)的时候,RabbitMQ就会自动将这条消息重新发布到Exchange上去,进而被路由到另一个队列。可以监听这个队列中的消息作相应的处理。消息变为死信的几种情况:

    • 消息被拒绝(basic.reject/basic.nack)同时 requeue=false(不重回队列)
    • TTL 过期
    • 队列达到最大长度,无法再添加

    (5)延迟队列:存储对应的延迟消息,当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。在 RabbitMQ 中并不存在延迟队列,但我们可以通过设置消息的过期时间和死信队列来实现延迟队列,消费者监听死信交换器绑定的队列,而不要监听消息发送的队列。

    (6)优先级队列:优先级高的队列会先被消费,可以通过 x-max-priority 参数来实现。但是当消费速度大于生产速度且 Broker 没有堆积的情况下,优先级显得没有意义。

    (7)RabbitMQ 要求集群中至少有一个磁盘节点,其他节点可以是内存节点,当节点加入或离开集群时,必须要将该变更通知到至少一个磁盘节点。如果只有一个磁盘节点,刚好又是该节点崩溃了,那么集群可以继续路由消息,但不能创建队列、创建交换器、创建绑定、添加用户、更改权限、添加或删除集群节点。也就是说集群中的唯一磁盘节点崩溃的话,集群仍然可以运行,但直到该节点恢复前,无法更改任何东西。


    相关阅读:

    Spring常见面试题总结

    SpringMVC常见面试题总结

    Mybatis常见面试题总结

    MySQL常见面试题总结

    Redis常见面试题总结

    RabbitMQ消息队列常见面试题总结

    ElasticSearch搜索引擎常见面试题总结

    计算机网络常见面试题总结

    操作系统常见面试题总结

    Java基础、集合、多线程常见面试题总结

    Java虚拟机常见面试题总结

    Java常见设计模式总结

    海量数据处理的方法总结

    展开全文
  • windows 消息队列

    2021-05-21 13:08:47
    为了避免对非界面线程创建消息队列带来的开销,所有的线程在被初始化后是没有消息队列的,只有在这个线程第一次调用用户函数或GDI函数时 系统才会为这个线程创建 消息队列。 现在我们基本上可以明白一件事,消息...
  • 这个时候加上了消息队列,服务器接收到用户的所有请求后,先把这些请求全部写入到消息队列中再排队处理,这样就不会导致同时处理多个请求的情况;如果消息队列长度超过可以承载的最大数量,那么我们可以抛弃当前用户...
  • 1、什么是消息队列: 1.1、消息队列的优点: (1)解耦:将系统按照不同的业务功能拆分出来,消息生产者只管把消息发布到 MQ 中而不用管谁来取,消息消费者只管从 MQ 中取消息而不管是谁发布的。消息生产者和消费...
  • linux消息队列总结

    2021-05-15 16:06:57
    1.消息队列简介实现linux进程通信的方式有5种:--信号(Singal)--管道(Pipe)--消息队列(Message)--信号量(Semaphore)每种进程通信方式实现方式和功能不一样,带来适用的场景也有所不同,消息队列是链表队列,它通过...
  • 消息队列MQ ,本质是个队列,其最简单的操作就是入队和出队,既按照程序决定何时何条件入队,和何时何条件出队。也就是说,遇到入队系统和出队系统的业务诉求不一致时的场景,就可以考虑是否用消息队列来实现了。可...
  • linux 消息队列 参数

    2021-05-13 10:52:45
    消息队列一、函数mq_open头文件mqueue.h;原型mqd_t mq_open(const char *name, int oflag, .../*mode_t mode,struct mq_attr* attr*/);函数功能创建消息队列;参数name:消息队列的名字,根据消息队列的规则,为了...
  • 一、队列简介 ...由于队列用来传递消息的,所以也称为消息队列。FreeRTOS中的信号量的也是依据队列实现的!所以有必要深入的了解FreeRTOS的队列。 1、数据存储 通常队列采用先进先出(FIFO)的存储缓冲机制,
  • 1.为什么使用消息队列 消息队列是一种“先进先出”的数据结构 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lpFhW0qd-1625639807196)(C:\Users\陈剑冰\AppData\Local\Temp\...
  • 2、多个进程可同时向一个消息队列发送消息,也可以同时从一个消息队列中接收消息。发送进程把消息发送到队列尾部,接受进程从消息队列头部读取消息,消息一旦被读出就从队列中删除。 二、结构 1、消息队列中消息本身...
  • 消息队列总结

    2021-05-18 10:58:59
    前言:关于消息队列应该大家都不陌生,在实际的项目中消息队列也无处不在,今天我和大家分享一下关于消息队列的问题。1、消息队列定义消息队列大家又经常称为MQ(message queue),从字面的含义来看就是一个存放消息的...
  • linux 消息队列的限制

    2021-05-18 16:50:54
    消息队列的系统限制作者:冯老师,华清远见嵌入式学院讲师。消息队列是System V的IPC对象的一种,用于进程间通信,会受到系统的限制,本文主要描述了三个限制。第一:议个消息的最大长度;第二:消息队列的最大容量;...
  • 常见消息队列 RabbitMq ActiveMq ZeroMq kafka等; 为什么使用RabbitMq? RabbitMQ是一个实现了AMQP(Advanced Message Queuing Protocol)高级消息队列协议的消息队列服务,用Erlang语言的。 ...
  • 分布式消息队列的演进

    千次阅读 2021-10-01 00:35:17
    作者:vincentchma,腾讯 IEG 后台开发工程师一、消息队列的演进分布式消息队列中间件是是大型分布式系统中常见的中间件。消息队列主要解决应用耦合、异步消息、流量削锋等问题,具有高...
  • 七、常见消息队列对比和选型 《Netty 实现原理与源码解析 —— 精品合集》 《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》 《Spring MVC 实现原理与源码解析 ...
  • 一、如何确保消息不丢失?1、检测消息丢失的方法可以利用消息队列的有序性来验证是否有消息丢失。在Producer端给每个发出的消息附加一个连续递增的序号,然后在Consumer端来检查这个序...
  • Windows 消息队列

    2021-04-14 02:06:08
    Windows 消息队列消息队列的功能使用消息队列的场合1. 客户端常常从网络上断开连接2. 客户端和服务端都在线消息1. 消息的类型2. 消息优先级3. 消息的传递模式4. 事务消息消息队列安装和使用消息队列1. 消息队列安装2...
  • linux消息队列概念

    2021-05-18 10:30:34
    消息队列的概念:消息队列提供了一种从进程向另一个进程发送一个数据块的方法。每个数据块都被认为是用一个类型,接收者进程接收的数据块可以有不同的类型值。我们可以通过发送消息来避免命名管道的同步和阻塞的问题...
  • 什么是消息队列

    2021-08-17 20:13:42
    一、消息队列概述 消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。目前使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,...
  • 高并发-消息队列

    2021-08-04 17:39:44
    一、消息队列 消息队列在分布式系统中主要是为了解耦和削峰。 什么是消息队列 我们可以把消息队列看作是一个存放消息的容器,当我们需要使用消息的时候,直接从容器中取出消息供自己使用即可。 消息队列是分布式...
  • FreeRTOS消息队列

    2021-02-01 20:27:59
    FreeRTOS消息队列 队列又称消息队列,是一种常用于任务间通信的数据结构, 队列可以在任务与任务间、中断和任务间传递信息,实现了任务接收来自其他任务或中断的不固定长度的消息,任务能够从队列里面读取消息,当...
  • JAVA-消息队列

    2021-02-28 16:05:53
    消息队列,可以在服务器接收到用户请求后,将这些请求加入消息队列,然后再一个一个处理。如果消息队列的长度超过限制,还可以把后来的用户请求丢掉,转入如出错,请刷新,或者404界面。2.在做项目的时候,如果...
  • 但是可能有性能问题,对于消息队列的可以如下参看 cat /proc/sys/kernel/msgmax cat /proc/sys/kernel/msgmnb 在配置文件中可以修改 个人建议你,使用消息队列时候,配合共享内存( 如果是同一进程,使用全局内存访问)...
  • 消息队列的使用场景有很多,最常见的使用场景有哪些? 1、商品秒杀 比如,我们在做秒杀活动时,会发生短时间内出现爆发式的用户请求,如果不采取相关的措施,会导致服务器忙不过来,响应超时的问题,轻则会导致...
  • qt代码实现消息队列通信 内容精选换一换HBase 1.X版本在RPC流程中,多个数据通信线程会争抢同一个缓存Buffer队列,代码以lock重入锁实现线程安全,锁抢占严重,导致HBase不能充分发挥CPU多核的能力。HBase 1.X版本的...
  • 消息队列作为UCOS-Ⅲ中任务间通信重要的一环,虽然底层原理较为复杂,但在使用中我们只需注意他的API调用即可,本文讲述UCOS-Ⅲ的消息队列API如何调用
  • RTT-消息队列

    2021-07-22 22:00:59
    RTT-消息队列 参考:《[野火®]《RT-Thread 内核实现与应用开发实战—基于STM32》 概念 消息队列就是一个线程给另一个线程发消息,收到消息就处理,没收到就挂起。 用户还可以指定挂起的线程时间 timeout;当队列...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 556,822
精华内容 222,728
关键字:

常见的消息队列