RabbitMQ个人小结

前言

小组分享

什么是MQ?

全称:Message Queue Middleware 消息队列中间件;

指利用高效可靠的消息传递机制进行与平台无关的数据交流;
通过提供消息传递和消息排队模型,它可以再分布式环境下扩展进程间的通信。

削峰填谷

消息的传递模式

① 点对点模式

在这里插入图片描述

② 发布/订阅模式(pub/sub)

在这里插入图片描述

RabbitMQ原理

本质上呢,就是一个生产者与消费者模型,主要负责接收、存储和转发消息。

在这里插入图片描述
假设将RabbitMQ整体抽象化:

在这里插入图片描述

形象点的理解:
寄快递,快递员上门取件,快递公司会暂存快递到集散点,运送到目的地后,由快递员送到收件人手里。

那么Rabbitmq就好比由快递公司、集散点和快递员组成的一个系统。

Broker

可以看作是服务器的节点,或者服务实例;一般情况下,我们就是看作rabbitmq的服务器。

队列

是Rabbitmq的内部对象,作用:用来存储消息。

在这里插入图片描述

最简单的实现方式;

现在考虑这样一个场景,:

想把包含:rabbitmq这类消息投递到队列1中;
想把包含:股票这类消息的投递到队列2中;

假设基于上面的简单模型,就很难实现;
所以,实际上生产者是将消息发送到交换器中,由交换器将消息路由到一个或多个队列中。
如果路由不到,可能返回给消费者,可能丢弃掉。

在这里插入图片描述

交换器

交换器可以理解为一个简单的实体;类似中转站;
负责将消息分门别类的发送到相应的队列中。

交换器的类型

类型说明
fanout它会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中
direct将消息路由到路由键绑定键完全匹配的队列中
topic对direct的扩展;对路由键支持模糊匹配;*匹配一个单词,#匹配多规格单词,可以是0个
headers该交换器不依赖路由键的匹配规则,而是根据消息内容中headers属性来匹配。基本不用

路由

当生产者发消息给交换器时,得告诉交换器这条消息应该去哪(队列)。
那么这个东东就是路由键routingkey).

这里需要注意:虽然生产者告诉了交换器这条消息应该去哪里,但是交换器又是怎么知道应该去哪个队列呢?
这里就需要将队列和交换器进行绑定,有了这层绑定关系,交换机就知道去哪里了;
这层绑定关系,我们称为 绑定键bindingkey)。

查阅大量资料,你会发现,绑定键会习惯性写成路由键。官方的解释为:绑定时的路由键;
所以通常我们会将这两个都统称为路由键

信道

Q:为什么不直接使用Connection来完成信道的工作呢?
A:假设一个应该程序有多个线程需要从RabbitMQ中消费消息,那么必然需要建立很多个Connection,也就是很多个TCP连接。而操作系统建立这种连接是非常昂贵的开销,而RabbitMQ
采用类型NIO的做法,选择TCP连接复用,既能减少开销,又能方便管理。

RabbitMQ 如何发送消息

上面我们知道了,从消息生产出来后,会经过交换器转发给队列

类似Java思想:先声明,在使用

① 创建交换器

channel.exchangeDeclare(exchangeName, "direct", true);

② 创建队列

String queueName = channel.queueDeclare();

③ 绑定交换器和队列

channel.queueBind(queueName, exchangeName, routingKey);

这里的路由键,我们也可以称为绑定键;用于决定交换器的消息转发给哪个队列

④ 发送消息

channel.basicPublish(exchangeName, routingKey, BasicProperties, message);

这里的路由键,决定消息发送给哪个交换器

RabbitMQ 如何消费消息

消费消息有两种模式:

  1. 推模式

和发送消息类似,前面三个步骤是一样的,第四步:

channel.basicConsume(queueName, autoAck, callback)

说明:

① 正常情况下,交换器和队列其实会提前创建好,所以消费端,其实不用再声明交换器队列了,因此直接使用即可。

  1. 拉模式

单条的获取消息。

GetResponse response = channel.basicGet(queue_name, autoAck);
response.getBody();

说明:
① 如果只想从队列中获得单条消息而不是持续订阅,那么建议使用Basic.Get进行消费。
② 理论上,可以将Basic.Get放入循环来实现类似推模式,但是这会严重影响性能。

RabbitMQ 如何持久化

RabbitMQ持久化分为三个部分:
① 交换器持久化
② 队列持久化
③ 消息持久化

交换器的持久化:

channel.exchangeDeclare(exchangeName, "direct", true);

第三个参数durable设置为true;如果设置为false,重启后,交换器就丢失了。

队列持久化:

channel.queueDeclare(queueName, durable, exclusive, autoDelete, args)

durable设置为true,因为消息时存放在队列中的,所以队列如果不持久话,消息一定会丢失。

消息持久化:

channel.basicPublish(exchangeName, routingKey, BasicProperties, message);

在发送消息时,利用BasicProperties将投递模式设置为2,消息就会被持久化:

new BasicProperties("text/plain", null, null, 2//投递模式, 0, null...);

持久化消息后,就能保证消息不丢失吗?

通过上面我们了解了,持久化的具体操作;
那么如果我们把,交换器、队列和消息都设置为持久化就能百分百保证数据不丢失吗?

A: 不行。
情形一:如果订阅消费队列使用的是autoAck=true,那么当消费者接收到相关消息后,就宕机了,这其实也算消息丢失;解决办法:设置为false,然后手动确认

情形二:持久化的消息,正确的存入RabbitMQ之后,并不是里面就同步存入磁盘中,因为这种落盘操作时需要调用操作系统fsync方法来进行同步落盘,这时消息只是在操作系统的缓存中,如果这段时间RabbitMQ服务节点发生了宕机,重启等异常,消息就会丢失。
解决办法:① 使用RabbitMQ 镜像队列机制,相当于配置了副本,如果主节点挂了,可以自动切换到从节点。
② 在发送端引入事务机制发送确认机制来保证消息确实是落盘了。

RabbitMQ学习笔记:生产者消息确认

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山鬼谣me

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值