Rabbitmq踩的坑以及一些总结记录

首先说说最近使用rabbitmq踩的坑,rabbitmq是基于erlang语言所写,所以下载使用rabbitmq的时候要先下载erlang 同时配置其环境变量。但是window系统下载rabbitmq和erlang耗时极其长,安装使用后,可能还会出现localhost:15672访问不了的情况,所以建议在VM虚拟机上使用centos7系统,安装docker,然后直接拉取rabbitmq镜像,几分钟就搞定了。

接下来进入主题,首先摆出几个概念:
RabbitMq首先是基于AMQP协议(高级消息队列协议),​ AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件同产品(中间件:比如rabbitmq),不同的开发语言等条件的限制。erlang:是一种语言(我也不了解)主要是三个特性: 高并发、高容错、软实时

大致的概念看完了,接下来进入关键问题了,为何我们要使用消息队列呢?
原因有三:
1、异步处理:可以提高系统的吞吐量,同一时间系统可以处理更多问题,而不会卡在一处地方。
2、解耦:系统与系统之间通过消息队列来传递消息,减少了系统之间的耦合度,无需知道其他系统的实现细节,反正我消息发出去就完事了。
3、流量削锋:可以通过控制消息的长度来控制请求的数量,缓解短时间内系统的高并发请求。
但是任何东西有利有弊,消息队列虽然方便,但是明显的我们一但使用消息队列,就说明我们还要写消息队列的代码,这不就增加了代码的复杂度。其二、消息队列一旦挂了呢,系统之间还靠什么来交互。

RabbitMQ的基本概念
Broker:消息队列服务器实体,里面存放交换机和队列
Exchange:消息交换机,就是把你发送的消息路由到哪个队列
Queue:消息队列载体,每个消息都会被投入到一个或者多个队列
Binding:绑定,作用是把exchange和queue按照路由规则绑定起来
Routing Key:路由关键字,exchange根据这个关键字进行消息投递
VHost:可以理解为虚拟broker,其内部均含有独立的queue、exchange和binding。重点在于它拥有独立的权限系统。
Producer:消息生产者
Consumer:消息消费者
Channel:消息通道,每个消息通道相当于一个会话任务Exchange到Queue的唯一线路需要由Exchange和Queue以及RoutingKey来决定
接下来看看rabbitMq的工作模式Rabbitmq的工作模式
1、simple模式(即为最简单的收发模式)
在这里插入图片描述
生产者发送消息到队列里面,不足:有可能造成消息的丢失
2、work工作模式(资源的竞争)
在这里插入图片描述
消息放入队列,有多个消费者,消费者会竞争消息,不足:高并发下某个消息可能会被多个消费者同时使用,可以设置一个开关(synchronized)
3、publish/subscribe发布订阅(共享资源)
在这里插入图片描述
(1)、每个消费者监听自己的队列(2)、生产者将消息发给broker,由交换机将消息转发到绑定到交换机的每个队列,每个绑定交换机的队列都将接受到消息
4、路由模式
在这里插入图片描述
创建消息的时候同时设置一个路由,生产者把消息发送给交换机的时候,交换机根据消息的路由信息,找到对应的路由绑定的队列,并把消息发送到对应队列上
5、topic主题模式(路由模式的一种)支持通配符,模糊匹配
在这里插入图片描述
6、RPC模式
在这里插入图片描述
关于MQ的一些思考
保证RabbitMQ消息的顺序性?有两种方案:1 是拆分为多个queue,每个queue对应一个consumer,这样就不会出现一个队列里面的消息被多个消费者消费,导致消息顺序不对问题。2、就一个queue对应一个consumer消息如何分发?首先要保证消息至少有一个消费者订阅,消息将以循环的方式发送给消费者,每条消息只会分发给一个订阅的消费者(前提是消费者能够正常处理消息并进行确认)

消息如何路由?消息在创建的时候要设置路由键,队列也通过路由键绑定到交换机上,这样消息到达交换机上的时候,交换机会根据路由键来决定你的消息发送到哪个队列上面去(不同的路由机有不同的规则)常用的有以下三种:fanout:如果交换器收到消息,将会广播到所有绑定的队列上direct:如果路由键完全匹配,消息就会被投递到相应的队列topic:可以使来自不同源头的消息到达同一个队列,使用topic交换器的时候,可以使用通配符

消息基于什么传输? TCP的创建与连接消耗很大,所以RabbitMQ使用信道的方式来传输数据,信道是建立在真实TCP连接内的虚拟连接,每条TCP的连接上信道数量没有限制

如何保证消息不被重复消费(幂等性)?
重复消费为何会发生:当消费者消费完信息后,会发送消息告知消息队列它已经把消息消费了,这个时候消息队列就会把相应消息给删除掉。但是这个时候问题就来了,如果消费者发送的这个消费完的消息没有被消息队列获取到,消息队列就不会把消息删除,这样消费者就有可能接受到重复的消息了。解决方案,最好是在消息里面加入标识,这样消费者在消费的时候就能够获取标识来判断自己是否已经消费过这个消息,从而能够避免重复消费

怎么能够确保消息正确发送到RabbitMQ,怎么确保消息接收方消费了消息发送方?:将信道设置为confirm模式(发送方确认模式),则在所有信道上发布的消息都会被指派一个唯一的ID 一旦消息被投递到目的队列后,或者消息被写入磁盘后,信道就会发送一个确认给生产者,包含消息的唯一ID,如果rabbitmq内部错误导致消息丢失,会发送一条未确认消息给生产方接收方:rabbitmq仅通过和消费者的连接是否中断来判断是否需要重新发消息,所以只要连接不中断,Rabbitmq就不会再给消费者发送消息了

什么情况下会出现 blackholed 问题?blackholed 问题,向 exchange 投递了 message ,而由于各种原因导致该message 丢失,但生产者却不知道。导致 blackholed 的情况:1.向未绑定 queue 的exchange 发送 message;2.exchange 以 rou_tingkey key_A 绑定了 queue queue_A,但向该 exchange 发送 message 使用的 routing_key 却是 key_B。

持久化机制对于message的利与弊持久化就是把消息写到磁盘,写磁盘比写到内存这个效率就要低很多了,而且也有可能出现上述所说的blackholed问题

RabbitMQ集群正常来说有三种模式:单机、普通集群、镜像集群
1、单机:基本上就是在自己电脑启动了玩玩(少用)
2、普通集群:将rabbitMQ部署到多台机器上,只创建一个queue去链接rabbitmq,但是每个实例都会同步这一个queue的数据。消费者如果连接的不是这个有queue的rabbitmq实例,会把数据从从queue拉取过来,这个方案的本质就是,让集群多个节点来服务一个queue。
3、镜像集群:这个和第二种的区别就是每个rabbitmq节点都有一个完整的镜像queue。

猜你喜欢

转载自blog.csdn.net/weixin_42683077/article/details/106675490