分布式消息队列-RabbitMQ 数据结构及应用场景

Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

1.各个消息队列对比

为什么使用消息队列?

1、实现异步:批量数据的异步处理


2.消息队列异步流程图

2、实现解耦:串行任务的并行化


3. 消息队列解耦流程图

3、流量削峰:高负载任务的负载均衡

4.消息队列流量削峰示例

4、实现广播:基于生产者消费者模型

4.消息队列广播示例

RabbitMQ 工作模型

1、RabbitMQ 通信协议为AMQP高级消息队列协议,区别于javaEE内部的通信协议JMS(Java Message Service),JMS耦合性强绑定于java语言

2、RabbitMQ 工作模型


5. RabbitMQ工作模型

说明:

Producer:生产者主要用于生产消息并且向Broker发送消息

Broker:RabbitMQ 所在主机

Virtual Host:虚拟主机,当一个公司有非常多的业务系统,这时所有的系统都需要创建自己的Exchange、Queue以及他们之间的绑定关系来实现基于MQ的消息通信,这种情况下一台主机会出现非常多的Exchange、Queue,这是非常混乱的,为了解决这个问题会在一个Broker创建很多的Virtual Host,不同Virtual Host之间是完全隔离,不可见的,通过这种方式解决了资源利用率和资源隔离的问题,类似于java的namespace

Exchange:交换机,实现消息灵活的分发,消息来了后Exchange会根据一定的规则把消息分发到不同的Queue,RabbitMQ 是不会把消息直接发送到Queue里,RabbitMQ 最常用只有三种交换机

Queue:队列,用来存储消息,是一个独立运行的进程,本身采用使用erlang语言编写的数据库,把消息保存在磁盘或者内存里面

Connection:TCP长连接,请求来了后,Broker会创建释放长连接当并发特别多的时候特别影响性能,考虑到资源利用率RabbitMQ 会在Connection里面引入Channel(虚拟连接)概念,当请求来了后只需要keep tcp长连接,在连接里面创建、释放Channel就可以了,可以大大节省系统资源

Channel:通道、虚拟连接

Consumer:消费者,当消息通过Producer发送到Exchange后,根据绑定规则查找消息路由到哪个Queue上去,此时Consumer会监听一个Queue,从中获取消息

交换机

1、Direct Exchange ——直连交换机

6.直连交换机工作模型

说明:

工作流程:首先创建一个直连类型交换机 GupaoDirectExchange,在创建四个队列 SPRING_QUEUE、DUBBO_QUEUE、MYSQL_QUEUE、TOMCAT_QUEUE,通过binding key把队列绑定到交换机上,发送消息的时候必须携带一个路由关键字,当消息到达直连类型交换机 GupaoDirectExchange时会根据路由关键字查询匹配队列。

实例:

// 向 GP_DIRECT_EXCHANGE交换机发送一个spring类型的消息为 today is sunday

channel.basicPublish("GP_DIRECT_EXCHANGE","spring","today is sunday ");

// 向 GP_DIRECT_EXCHANGE交换机发送一个tomcat类型的消息为 today is Saturday

channel.basicPublish("GP_DIRECT_EXCHANGE","tomcat","today is Saturday");

2、Topic Exchange ——主题类型交换机

6. 主题交换机工作模型

说明:

工作流程:同直连交换机一样

实例:

# 代表0个或多个单词

* 代表1个单词

// "junior.netty"参数说明:绑定规则可以匹配的有 ‘junior.#’、‘#.netty’,向JUNIOR_QUEUE、NETTY_QUEUE队列发送消息

channel.basicPublish("GP_TOPIC_EXCHANGE","junior.netty","today is Saturday");

3、Fanut Exchange —— 广播类型交换机

7.  广播交换机工作模型

工作流程:没有任何关键字,所有的队列绑定到交换机上。当交换机接收到消息后,会分发到所有和当前交换机绑定的队列上

消息可靠性投递分析    

7.  队列工作模型

1、如何确保消息发送到RabbitMQ服务器?

答:需服务端确认,有两种方式可以实现

事务模式

//将channel(发送消息通道)设置成事务模式(和数据库的事务不是一回事,仅仅只是做事务确认)

channel.txSelect();

//提交事务

channel.txCommit();

//事务回滚

channel.txRollback();

该种方式的缺点很明显:1,阻塞的,发送一条消息必须在commit后才可以发送,基本会榨干rabbitmq服务器的资源,大大降低发送消息的速率,发送一条确认一条效率低下


7.  事务模式步骤

 Confirm模式

//将channel设置为confirm模式

channel.confirmSelect();

if(channel.waitForConfirms){

//消息发送成功

}


8. Confirm模式步骤

2、如何确保消息路由到正确队列?

答:当有路由映射失败的时候(这种情况非常少)设置路由保证,路由保证有两种方式可以实现

        1、在channel上设置参数 mandatory = true + ReturnListener

        2、备份交换机

3、如何确保消息正确的在队列存储?

答:队列是一个独立运行的进程,使用了elang编写的一个数据库将数据保存在内存中,而内存中的数据做持久化有以下三种方式

        1、队列持久化

        2、交换机持久化

        3、消息持久化 

4、如何确保消息从队列正确的透底到消费者?

答:需消费者应答,可以通过以下方式实现

       channel.basicAck();//手工应答

       channel.basicReject();//单条拒绝

       channel.basicNack();//批量拒绝

5、如果以上四个措施都执行了能保证消息一定送达吗?

答:不能的,因为流程中各个环节是孤立的,如果这种情况发生了可以通过以下几种方式实现

      1、消费者回调  (收到消息后告诉生产者,1、假如消息发送十分钟还无应答,可以用定时任务重发或者确认,2、应答消息)

      2、补偿机制 (消费者挂了,1、消息重发(限制次数),2、异步对账)

      3、消息幂等性

6、如何实现延时队列(比如电饭煲的定时,过期退款)?

答:1、延时队列插件

       2、TTL(Time To Live )

             1、队列里面消息过期时间

             2、单条消息的过期时间

             3、死信交换机,创建队列的时候指定一个死信交换机,如果消息没有设置过期时间,当消息过期后可以发送到死信交换机,通过死信交换机去处理消息,死信交换机也是一个普通的交换机可以绑定队列。

7、如何保障顺序消费(多个生产者发送消息队列,有多个消费者的时候)?

答:1、一个队列只有一个消费者

       2、全局id(MsgID,parentID)

this is end ,编写不易,看完记得点赞哦!

你可能感兴趣的:(分布式消息队列-RabbitMQ 数据结构及应用场景)