一、介绍

消息队列:是分布式系统中重要的组件,其通用的使用场景可以简单地描述为:当不需要立即获得结果,但是并发量有需要进行控制的时候,差不多就是需要使用消息队列的时候;

消息队列主要解决了应用耦合、异步处理、流量削峰等问题;

当前使用较多的消息队列由rabbitmq、rocketmq、activemq、kafka等;

二、使用场景

1、应用耦合:将应用进行耦合

具体场景:用户下单后,订单系统需要通知库存系统

(1)传统做法缺点:加入库存系统无法访问,则订单减库存将失败,从而导致订单失败,订单系统与库存系统耦合;

(2)使用消息队列

订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功;

库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作;

假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了,实现订单系统与库存系统的应用解耦;

(2)异步处理

多应用对消息队列中同意消息进行处理,应用间并发处理消息,相比串行处理,减少处理时间

具体场景:用户为了使用某个应用,进行注册,系统需要发送注册邮件并验证短信;

串行方式:新注册信息生成后,先发送注册邮件,再发送验证短信;

并发处理:新注册信息写入后,由发短信和发邮件并行处理;

若使用消息队列:在写入消息队列后立即返回成功给客户端,则总的响应时间依赖于写入消息队列的时间,而写入消息队列的时间本身是可以很快地,基本可以忽略不计,因此总的处理时间相比串行提高了2倍,相比并行提高了一倍;

(3)限流削峰:广泛应用于秒杀或抢购活动中,避免流量过大导致应用系统挂掉的情况

应用场景:秒杀活动,一般因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列;

作用:

可以控制活动的人数;

可以缓解短时间内高流量压垮应用;

用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面;

秒杀业务更具消息队列中的请求信息,在做后续处理;

三、消息队列的两种模式

1、p2p模式

(1)每个消息只有一个接收者,即一旦被消费,消息就不再消息队列中

(2)发送者和接收者健美有依赖性,发送者发送消息之后,不管有没有接收者在运行,都不会应当想到发送者下次发送消息;

(3)接收者在成功接收消息之后需要向队列应当成功,一边消息队列删除当前接受的消息

2、Pub/Sub模式(发布/订阅)

(1)每个消息可以有多个订阅者

(2)发布者和订阅者之间有时间上的依赖性。针对某个主题toplic的订阅者,它必须创建一个订阅之后,才能消费发布者的消息

(3)为了消费消息,订阅者需要订阅该角色主题,并保持在线运行

四、RabbitMQ集群

RabbitMQ模式大概分为三种:单一模式、普通模式(默认的集群模式)、镜像模式

镜像模式:把需要的队列做成镜像模式,存在于多个节点,属于RabbitMQ的HA方案,在对业务可靠性要求较高的场合中比较适用,在这个模式的基础上再配置镜像模式以实现高可用;

RabbitMQ集群节点包括内存结点、磁盘节点。顾名思义内存节点就是将所有数据放在内存,磁盘节点就是将数据放在磁盘。如果在投递消息时,打开了消息的持久化,那么即使是内存结点,数据还是安全的放在磁盘。

一个rabbitmq集群中可以共享user、vhost、queue、qxchange等,所有的数据和状态都是必须在所有节点上复制的;

内存节点:只保存状态到内存。

磁盘节点:保存状态到内存和磁盘。

内存节点虽然不写入磁盘,但它执行比磁盘节点要好。集群中,只需要一个磁盘节点来保存状态就足够了;如果集群中只有内存节点,那么不能停止它们,否则所有的状态,消息等都会丢失;

1、普通集群准备环境

三台服务器:

10.35.152.3 rabbitmq-1

10.35.152.8 rabbitmq-2

10.35.152.26 rabbitmq-3

首先三台服务器都需要做域名解析;

(1)安装rabbitmq软件:
dnf -y install epel-release gcc-c++ unixODBC openssl-devel ncurses-devel
curl -s http://packagecloud.io/install/repositories/rabbitmq/erlang/scripts.rpm.sh | sudo  bash
dnf -y install erlang-26.2.5.4-1.el9.x86_64
##测试
erl
dnf -y install rabbitmq-server-3.12.10-1.el8.noarch.rpm
systemctl daemon-reload
systemctl start rabbitmq-server
##每台服务器都开启rabbitmq的web操作页面;
rabbitmq-plugins enable rabbitmq_management
##创建用户
rabbitmqctl add_user newrain 123456      #创建用户
rabbitmqctl set_user_tags newrain administrator     #设置为管理员
rabbitmqctl list_user    #查看用户
rabbitmqctl set_permission -p "/" newrain ".*" ".*" ".*"
#此处设置的三个权限是配置权限、读权限、写权限;

https://www.rabbitmq.com/which-erlang.html #查看rabbitmq和erlang兼容版本

https://packagecloud.io/rabbitmq/erlang #erlang版本选择

https://www.rabbitmq.com/news.html #rabbitmq版本选择

(2)开始部署集群

首先创建好数据存放目录和日志存放目录;

mkdir -p /data/rabbitmq/data
mkdir -p /data/rabbitmq/logs
chown -R rabbitmq.rabbitmq /data/
#创建配置文件:
vim /etc/rabbitmq/rabbitmq-env.conf
RABBITMQ_MNESIA_BASE=/data/rabbitmq/data
RABBITMQ_LOG_BASE=/data/rabbitmq/logs
systemctl restart rabbitmq-server

拷贝erlang.cookie

rabbitmq的集群是依附于erlang的集群来工作的,所以必须先构建erlang的集群景象。

这个cookie文件存放在/var/lib/rabbitmq/.erlang.cookie中,文件是400的权限,所以必须保证各节点cookie一致,不然节点之间就无法通信。可以使用scp将文件拷贝到其他两台服务器上;

如果执行#rabbitmqctl stop_app 这条命令报错:需要执行chmod 400 .erlang.cookie/chown rabbitmq.rabbitmq .erlang.cookie

(3)添加节点

将rabbitmq-2、rabbitmq-3作为内存节点加入到rabbitmq-1节点集群中;

systemctl restart rabbitmq-server
rabbitmqctl stop_app    #停止节点
rabbitmqctl reset   #如果有数据需要重置,没有则不用
rabbitmqctl join_cluster --ram rabbit@rabbitmq-1   #添加到磁盘节点
rabbitmqctl start_app   #启动节点

每台服务器都需要这样去添加节点;

默认的rabbitmq启动后是磁盘节点,在这个cluster命令下,mq-2和mq-3是内存结点

如果mq-2、mq-3都要做磁盘节点的化,去掉--raw参数即可

如果想要更改节点类型,可以使用命令:rabbitmqctl change_cluster_node_type disc,前提是不许停掉rabbit应用;

查看集群状态:可以在集群任意节点上执行:rabbitmqctl cluster_status

在rabbitmq集群中,必须有一个磁盘节点,否则数据无法写入到集群中,当磁盘节点当掉后,集群将无法写入新的队列元数据信息;

2、RabbitMQ镜像集群配置

上面已经完成RabbitMQ默认集群,但并不保证队列的高可用性,尽管交换机、绑定这些可以复制到及群里的任何一个节点,但是队列内容不会复制。但队列节点宕机直接导致该队列无法应用,只能等待重启,所以要想在队列节点宕机或故障也能正常应用,就要复制队列内容到集群里的每个节点,必须要创建镜像队列;

创建镜像集群:

rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
此作者没有提供个人介绍
最后更新于 2024-12-09