RabbitMQ学习笔记

筅森魡賤 提交于 2020-03-09 18:44:30

1.消息中间件的核心设计思想
    采用异步通讯、自动补偿与重试分布式事务、解决流量削峰问题、系统的解耦

2.消息中间件常用名词:
    Broker 消息转发端,消息中间件Server端;
    Message 发送的消息内容
    roducer 生产者,向Server端投递消息;
    Consumer 消费者,向Server端获取消息
    MessageId 消息全局id  解决消息幂等性问题    
    
3.主流的MQ对比分析
    ActiveMQ: 基本淘汰(老项目使用) 够轻巧(源代码比RocketMQ多),支持持久化到数据库,
                  对队列数较多的情况支持不好。
    RabbitMQ: 结合erlang语言本身的并发优势,支持很多的协议:AMQP,XMPP, SMTP, STOMP,
                  也正是如此,使的它变的非常重量级,更适合于企业级的开发。
    RocketMQ: 阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0版本名称改为RocketMQ,
                  是阿里参照kafka设计思想使用java实现的一套mq,同时将阿里系内部多款mq产品
                  (Notify、metaq)进行整合,只维护核心功能,去除了所有其他运行时依赖,
                  保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下mq的架构,
                  目前主要多用于订单交易系统。
    Kafka:    Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统,
                具有以下特性:高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率;
                高堆积:支持topic下消费者较长时间离线,消息堆积量大;

4.RabitMQ环境的基本安装
    1.下载并安装erlang,下载地址:http://www.erlang.org/download
    2.配置erlang环境变量信息
          新增环境变量ERLANG_HOME=erlang的安装地址
          将%ERLANG_HOME%\bin加入到path中
    3.下载并安装RabbitMQ,下载地址:http://www.rabbitmq.com/download.html
          注意: RabbitMQ 它依赖于Erlang,需要先安装Erlang。                
          
5.Virtual Hosts:
    像mysql有数据库的概念并且可以指定用户对库和表等操作的权限。那RabbitMQ呢?
    RabbitMQ也有类似的权限管理。在RabbitMQ中可以虚拟消息服务器VirtualHost,每
    个VirtualHost相当月一个相对独立的RabbitMQ服务器,每个VirtualHost之间是相互
    隔离的。exchange、queue、message不能互通。

6.公平队列实现原理
    Mq服务器端每次只会给消费者发送一条消息,如果消费者没有返回ack,就不会继续发送消
    息。
    
7.如何保证消息不丢失
    1.生产者 确保我们的生产者将消息投递到MQ成功; 消息确认机制如果开启了消息持久化的机制,必须消息持久化成功才会应答给生产者
        // 开启生产确认消息投递机制   channel.confirmSelect();
         channel.waitForConfirms()==true  投递成功
    2.消费者 确保我们的消费者消费消息成功 采用手动ack确认
    3.MQ服务器端 需要将数据持久化到我们的硬盘
  其他情况下:  硬盘坏了、持久化的过程断电了?    
    如何解决 最好通过表记录每次生产者投递消息,如果长期没有被消费,手动的补偿消费。
    
8.如果在生产者投递消息失败的情况,在那些场景?
    1.MQ挂了 解决做心跳检测(heartbeat),自动重启,多次重启失败发邮件运维
    2.Mq拒绝接受消息 (队列满了) 就采用手动补偿或者日志表记录下即可

9.Rabbitmq如何开启持久化的功能?
    1.默认的情况下mq服务器端创建队列和交换机都是持久化的
    2.如果是代码创建的话,将该值设置为durablet

10.Rabbitmq发布订阅的实现原理
    核心思想:
        一个生产者投递消息,可以被多个不同的队列实现消费;
    实现原理:
        多个不同的队列绑定相同交换机,生产者只需要将消息投递到交换机之后,
        在由交换机将消息转发到所有绑定的队列实现消费。    
        
11.Direct exchange(直连<路由>交换机)
     Fanout exchange(扇型<广播>交换机)
     Topic exchange(主题交换机)
  交换机核心作用:分发路由消息、中专
    队列:容器存放多个不同消息 遵循先进先出的原则
    消息:传递的参数
    路由键:交换机根据这样的路由键的值,发送不同的队列中 匹配过程
    扇型交换机主要的特征:只要队列绑定同一个交换机,生产者将消息投递到交换机中,交换机会将消息发送给所有绑定的队列进行存放消息。
    Direct exchange(直连交换机):根据生产者投递不同的路由键,在交换机发送到队列实现匹配路邮件
    Topic 主题交换机:根据路邮键的key实现模糊匹配到队列存放。    

12.    RabbitMQ如果产生了消息堆积如何处理
    产生的背景:如果没有及时的消费者消费消息,生产者一直不断往队列服务器存放消息
        会导致消息堆积
    两种场景:
        1.没有消费者消费的情况下: 死信队列、设置消息有效期
              相当于对我们的消息设置有效期,在规定的时间内如果没有消费的话,自动过期,
              过期的时候会执行客户端回调监听的方法将消息存放到数据库记录,后期实现不补偿。

        2.有一个消费者消费的情况:应该提高我们的消费者 消费实现集群    
        
13.    RabbitMQ如何彻底保证我们的消息不丢失
    1.MQ服务器端应该消息持久化到硬盘
    2.生产者使用消息确认机制百分能够将消息投递到MQ成功
    3.消费者使用手动acm机制确认消息百分百消费成功
    如果队列容量满了,在继续投递可能会丢失 死信队列
    死信队列:称做为备胎队列,消息中间件队列因为某种消费拒绝存放该消息,可以转移到死信队列中存放。
    死信队列产生的背景
        1.生产者投递消息到MQ中,消息过期了,转入死信队列;
        2.队列的已经达到最大长度(队列存放消息满了)MQ拒绝接受存放该消息。
        3.消费者多次消费该消息失败的情况,也会存放死信。
    死信队列不能够和正常队列存放在同一个服务器中,应该分开服务器存放

14.订单30分钟未支付,系统自动超时关闭有哪些实现方案?
    1.基于任务调度实现,效率是非常低,耗服务器性能
    2.基于redis过期key实现.用户下单的时候,生成一个令牌(有效期)30分钟,存放到我们redis;
        redis.set(orderToken ,orderID) 下单时候存放到redis,并存储id入库,30分钟过期,
        redis客户端监听,过期获取到orderId,拿orderId去查订单,没有支付则,订单关闭,库存增加
        缺点:非常冗余 ,会在表中存放一个冗余字段
    3.基于MQ的延迟队列实现(最佳)    死信队列
        原理:当我们在下单的时候,往MQ投递一个消息设置有效期为30分钟,但该消息失效的时候(没有被消费的情况下),
             执行我们客户端一个方法告诉我们该消息已经失效,这时候查询这笔订单是否有支付.
        具体步骤:下单投放消息到A交换机(过期时间30分钟),消息到aa队列(绑定死信交换机),不设置aa队列的消费者.
                 30分钟后,过期消息投递到死信交换机,死信队列,又死信消费者消费,判断订单id
                 时候支付,支付->return  未支付->关闭订单,返还库存

    4.redis的延迟队列  https://blog.csdn.net/zhangshengqiang168/article/details/100130523

15.RabbitMQ自动补偿机制触发:(多用于调用第三方接口)
    1.当我们的消费者在处理我们的消息的时候,程序抛出异常情况下(默认无限次数重试)
    2.应该对我们的消息重试设置间隔重试时间,比如消费失败最多只能重试5次,间隔3秒(防止重复消费,幂等问题)
    
16.如果重试5次,也就是15秒内重试还是失败情况下应该如何处理?
    1.默认情况下,重试多次还是失败的话,会自动删除该消息(消息可能会丢失)
     解决思路:
      A:如果重试多次还是失败的情况下,最终存放到死信队列.
      B:采用表日志记录,消费失败错误的日志记录 后期人工自动对消息实现补偿.

17.分布式事务产生的背景?
    1.RPC通讯中每个服务都有自己独立的数据源,每个数据源都互不影响.
    2.在单个项目中存在多个不同jdbc连接(多数据源)
    
18.如何基于我们的MQ解决我们的分布式事务的问题(最终一致性)
    1.确保我们的生产者往我们的MQ投递消息一定要成功.(生产者消息确认机制confirm),实现重试.
    2.确保我们的消费者能够消费成功(手动ack机制),如果消费失败情况下,MQ自动帮消费者重试.
    3.确保我们的生产者第一事务先执行成功,如果执行失败采用补单队列.
          

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!