zoukankan      html  css  js  c++  java
  • RabbitMQ消息中间件的理解

    是什么:微服务之间的消息通信方式
    常见的消息中间件:
      ActiveMQ:基于JMS
      RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好
      RocketMQ:基于JMS,阿里巴巴产品,目前交由Apache基金会
      Kafka:分布式消息系统,高吞吐量
    MQ实现方式:AMQP (只是一种协议所以支持跨平台)与jms(必须是java语言) 
    好处:(转载---为什么使用MQ说明: https://www.cnblogs.com/williamjie/p/9481780.html )
        1、解耦,消费方只需要订阅读取消息即可
        2、灵活性,峰值处理好
        3、MQ的处理异步的,这样就提升了系统的处理性能。
        4、可恢复性
        5、顺序保证
        6、缓冲能力,消息中间件像是一个巨大的蓄水池,将高峰期大量的请求存储下来慢慢交给后台进行处理,对于秒杀业务来说尤为重要
    缺点:
        1、系统复杂度增加,考虑消息的重复问题,消息丢失问题。
        2、一般消息中间件的服务崩溃了,涉及的相关系统就不可用了。
     
    Rabbit 执行原理:
       消息生产方推送消息到队列,消息放消费队列中的消息。(下图是基本消费模型)
       
    消息模型:*******重要******
       基本消息模型         消息发送方   -----》队列  ------》 一个消息消费方
       work 消息模型      消息发送方   -----》 队列 ------》 多个消息消费方  
    消息发送流程:
         1) 一个队列绑定多个消费者
         2)消费者呈合作者分别处理一部分消息解决消息堆积问题。
     
     发布订阅消息模型(该模型包含基本与work 消息模型的 消息发布方 -->交换机 -->队列 -->消息订阅方 
     一、Fanout:在广播模式下,消息发送流程是这样的:
    • 1) 消息生产方生产消息发送到交换机

    • 2) 消费方监听queue(队列)

    • 3) 队列与Exchange(交换机)绑定

    • 4) 生产者发送的消息发送到交换机(在代码中将队列与交换机绑定就发送给对应队列,生产者无法决定)。

    • 5) 交换机把消息发送给绑定过的所有队列

    • 6) 队列中的消息被消费者监听到从而执行。实现一条消息被多个消费者消费

     二、Direct:控制发布的消息的队列被哪些订阅方收到
     特点: 消息生产方会指定routingKey 的关键字,这样交换机就会将消息发送给与该routingkey完全匹配的队列。
     例如:在路由模式中,我们将添加一个功能 - 我们将只能订阅一部分消息。 例如,我们只能将重要的错误消息引导到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。
       

      P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key 如:rabbit 

      X:Exchange(交换机),接收生产者的消息,然后把消息递交给 与routing key完全匹配的队列

      C1:消费者,其所在队列指定了需要routing key 为 error 的消息

      C2:消费者,其所在队列指定了需要routing key 为 info、error、warning 的消息

    三、Topic模型 : 和Direct 一样。只是可以使用通配符进行匹配(更加灵活通用)

    上图中:Q1匹配所有的橙色动物。Q2匹配关于兔子以及懒惰动物的消息。

    以下的routingKey 配置后哪些会进入Q1,Q2队列。

      quick.orange.rabbit  Q1 Q2

      lazy.orange.elephant  Q1 Q2

      quick.orange.fox  Q1

      lazy.pink.rabbit  Q2

      quick.brown.fox  不匹配任意队列,被丢弃

    面试热点: 以下P方 = 消息生产方   C方 = 消息消费方
     一、如何保证消息不丢失?  问到过!
      1、采用消费者消息确认机制(ACK),ACK分为手动和自动,
      自动ACK:消费方接受到消息则队列中的消息就会被删除 
      手动ACK:如果在接受到消息后发生了错误抛异常 这种情况应该使用手动确认 类似手动启动关闭事务这样
      2、采用生产者消息回执确认机制:
      消息生产者 交换机发送消息发送成功后,交换机回执ACK给消息生产者

    二、如果MQ服务器挂掉怎么办? 
      1、搭建集群
      2、将消息持久化,在spring集成中消息和队列以及交换机 都是持久化的

    三、如何解决队列中的消息积压过大?
       work 消息模型 配置多台消息的消费方进行消费。

    四、幂等性(如何解决消息被重复执行):  问到过!
    消息被重复发送,例如下订单我点了两次也许是网络原因点了2次。
    发生原因:当交换机回执ACK给P方时,由于网络故障导致生产方未收到消息,当网络恢复
    P方没有收到ACK回执则重新发送一条消息导致消息重复。
    解决方案:
        给消息设置唯一ID,判断该消息被消费过,然后再业务方进行去重。
    实现方式两种:
    1、在ZK中创建node 当判断是否重复的时候就去创建node 如果存在创建会报错。
    2、使用redis 当放入MQ后就往redis 中存入一个唯一id 判断重复的时候就去看看是否存在,存在即重复。

    五、延迟队列实现方式:问到过!
    场景介绍:商品订单超过半小时自动删除。
    解决方案:(通过TTL死信 与 DLX 死信队列实现。)
        1、设置消息的有效期,例如30Min,当超过该效期,则该信息变为死信 (TTL)
        2、当出现死信,MQ提供对于死信处理的死信队列,例如当订单超过半小时,则将消息放入死信队列,然后由绑定死信队列的消费方进行处理,从而将订单删除。(DLX) 这样就利用了MQ的特性实现了延迟队列。
     
    扩展:一般死信处理情况有三种:
    1、消息超时
    2、消息被拒绝
    3、队列达到最大长度
  • 相关阅读:
    Gartner:当商业智能成熟度低时,如何加快分析采用率
    年薪50万的大数据分析师养成记
    数据化管理在餐饮业中的应用
    linux下查看本机socket端口详细信息
    nginx模块编程之获取客户ip及端口号
    大小端模式转换函数
    Nginx代码调试——gdb工具
    Nginx入门之两种handler函数的挂载方式
    Nginx重要结构request_t解析之http请求的获取
    Nginx_handler模块发开(hello模块结构解析)
  • 原文地址:https://www.cnblogs.com/lanSeGeDiao/p/11090717.html
Copyright © 2011-2022 走看看