RabbitMQ的幂等性和集群负载均衡

本文介绍了RabbitMQ的幂等性实现,通过示例代码展示了如何确保消息处理的幂等性,以防止重复操作。接着讨论了RabbitMQ集群的普通模式和镜像模式,解释了为什么需要集群以及集群的工作原理。在集群配置中,详细演示了从单机到普通集群再到镜像集群的步骤,并测试了主从节点间的高可用性。最后提到了使用Haproxy进行负载均衡,以提升系统的抗并发能力和可用性。
摘要由CSDN通过智能技术生成

RabbitMQ的幂等性和集群负载均衡

1、RabbitMQ的幂等性

  假设你买了一样东西,已经付款了,但是返回结果的时候,你的网络异常了,此时钱已经扣了,用户再次点击支付,就会进行二次扣款,返回结果成功了,但是这样合理嘛?肯定不行的,因为你支付了两次,这样不合理,因为你只需要支付1次就可以。
  以前我们只需要将数据操作放到事务中,发生错误立即回滚就行,但是再次相应还是可能会出现网络终端或者异常等情况,所以现在就需要保证用户点击一次或者多次所产生的结果一样。

那么此时就可以去这样理解幂等性:

  • 对于一个资源,不管你请求一次还是请求多次,对该资源本身造成的影响应该是相同的,不能因为重复相同的请求而对该资源重复造成影响。注意关注的是请求操作对资源本身造成的影响,而不是请求资源返回的结果,这就是幂等性。

上代码:

@Component
public class MyListener {

    @Autowired
    private RedisTemplate redisTemplate;
    @RabbitListener(queues = "queue")
    public void listener(Message msg, Channel channel) throws  Exception{
        //Boolean absent = 
        Object o = redisTemplate.opsForValue().get(msg.getMessageProperties().getDeliveryTag());
        if(o==null){
            //业务代码
            try {
                System.out.println("完成业务功能");
                redisTemplate.opsForValue().set(msg.getMessageProperties().getDeliveryTag(), "yth");
                channel.basicAck(msg.getMessageProperties().getDeliveryTag(), true);
            }catch (Exception e){
                channel.basicNack(msg.getMessageProperties().getDeliveryTag(),true,true);
            }
        }else{
            channel.basicAck(msg.getMessageProperties().getDeliveryTag(),true);
        }
    }
}

这里只能列出来代码,测试结果是没有办法得到。

2、RabbitMQ集群

2、1为什么要使用集群?

集群是为了解决单机可能出现宕机等引发的不可用的问题,可以有效提高程序的可用性和可靠性以及抗并发的能力。
集群分为两种模式:

  1. 普通模式:默认的集群模式。

  默认集群对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。当rabbit01节点故障后,rabbit02节点无法取到rabbit01节点中还未消费的消息实体。如果做了消息持久化,那么得等rabbit01节点恢复,然后才可被消费;如果没有持久化的话,就会产生消息丢失的现象。

  1. 镜像模式:把需要的队列做成镜像队列,存在于多个节点。

  镜像集群把需要的队列做成镜像队列,存在与多个节点属于RabbitMQ的HA方案。该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用。

2、2RabbitMQ普通集群

这里采用了伪集群:一台主机启动多个RabbitMQ服务。
先停止原有的RabbitMQ服务:

service rabbitmq-server stop
  1. 开启第一个节点:
RABBITMQ_NODE_PORT=5673 RABBITMQ_NODENAME=rabbit1 rabbitmq-server start

在这里插入图片描述

放行15672端口:

firewall-cmd --zone=public --add-port=15672/tcp --permanent
firewall-cmd --reload
firewall-cmd --zone=public --query-port=15672/tcp

在浏览器登录查看是否可以进入可视化管理界面:
提示:rabbit1是使用的15672端口
在这里插入图片描述

  1. 开启第二个节点:
RABBITMQ_NODE_PORT=5674 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15674}]" RABBITMQ_NODENAME=rabbit2 rabbitmq-server start

放行15674端口:

firewall-cmd --zone=public --add-port=15674/tcp --permanent
firewall-cmd --reload
firewall-cmd --zone=public --query-port=15674/tcp

在浏览器登录查看是否可以进入可视化管理界面:
提示:rabbit2是使用的15674端口
在这里插入图片描述

  1. 设置主从关系:
     rabbit1作为主节点:
rabbitmqctl -n rabbit1 stop_app
rabbitmqctl -n rabbit1 reset	 
rabbitmqctl -n rabbit1 start_app

  rabbit2作为从节点:

’ '里面是你的主机名

rabbitmqctl -n rabbit2 stop_app
rabbitmqctl -n rabbit2 reset
rabbitmqctl -n rabbit2 join_cluster rabbit1@'yth'
rabbitmqctl -n rabbit2 start_app

在可视化界面里面查看,发现已经绑定上了。
在这里插入图片描述

  1. 在任意一个节点上创建队列,会发现两个节点上都出现这个myqueue。

在这里插入图片描述

此时在队列中发布一条信息,主节点上是有信息。

在这里插入图片描述

关闭主节点,看看子节点上的信息是否会消失。
在这里插入图片描述

发现主节点关闭,子节点也会掉,这样不行,太假了,此时就需要用到镜像集群了。

2、3RabbitMQ镜像集群

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

  • 镜像队列是基于普通的集群模式的,然后再添加一些策略,所以你还是得先配置普通集群,然后才能设置镜像队列,我们就以上面的集群接着做。

  1. 在普通集群的基础上配置镜像集群

在这里插入图片描述

  1. 如下图:显示蓝色的+1,是正确的,如果是红色的,等待20秒左右,再看看是否变成蓝色,我在设置的时候也出现了这个问题,等待20秒后就变成蓝色的了。

在这里插入图片描述

  1. 再次关闭主节点,查看子节点是否还能获取主节点的信息。
    经过测试发现,主节点已经关闭,子节点还可以继续获取信息。
    在这里插入图片描述

3、负载均衡

此处就不再对负载均衡做简介了,类型和nginx一样。
链接:【csdn下载
链接:百度云链接
提取码:h7ox

tar -zxvf haproxy-1.6.5.tar.gz -C /usr/local
cd /usr/local/haproxy-1.6.5
make TARGET=linux31 PREFIX=/usr/local/haproxy
make install PREFIX=/usr/local/haproxy
mkdir /etc/haproxy
vim /etc/haproxy/haproxy.cfg

将下面代码块中的内容复制到文件里面

global
	log 127.0.0.1 local0 info
	maxconn 5120
	chroot /usr/local/haproxy
	uid 99
	gid 99
	daemon
	quiet
	nbproc 20
	pidfile /var/run/haproxy.pid

defaults
	log global
	
	mode tcp

	option tcplog
	option dontlognull
	retries 3
	option redispatch
	maxconn 2000
	contimeout 5s
   
     clitimeout 60s

     srvtimeout 15s	
#front-end IP for consumers and producters

listen rabbitmq_cluster
    # haproxy暴漏的端口号
	bind 0.0.0.0:5672
	
	mode tcp
	#balance url_param userid
	#balance url_param session_id check_post 64
	#balance hdr(User-Agent)
	#balance hdr(host)
	#balance hdr(Host) use_domain_only
	#balance rdp-cookie
	#balance leastconn
	#balance source //ip
	
	balance roundrobin
	    # haproxy代理的rabbit服务
        server node1 127.0.0.1:5673 check inter 5000 rise 2 fall 2
        server node2 127.0.0.1:5674 check inter 5000 rise 2 fall 2

listen stats
    # haproxy的图形化界面这里是你的LinuxIP地址
	bind 192.168.31.33:8100
	mode http
	option httplog
	stats enable
	stats uri /rabbitmq-stats
	stats refresh 5s

开启Haproxy:

/usr/local/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg

//查看haproxy进程状态
ps -ef | grep haproxy

如果开启报错:请再次使用vim /etc/haproxy/haproxy.cfg文件,看看第一行是不是缺少字母了。

访问以下地址对mq节点进行监控:

http://192.168.213.181:8100/rabbitmq-statss

此时我的节点一是关闭,节点2是开启的,信息无误。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
RabbitMQ 作为一款开源的消息队列系统,为了保证消息的可靠传输和处理,采用了以下几个关键机制: 1. **确认机制(Acknowledgements)**:当消费者成功接收到消息后,会向 RabbitMQ 中心节点发送一个确认,如果中心节点没有收到确认,会重新将消息放入队列等待消费者的再次处理,直到超时或达到重试次数。 2. **持久化(Persistence)**:RabbitMQ 可以将消息写入磁盘,即使服务器宕机也能保证数据不丢失,恢复后可以从上次的位置继续处理。 3. **事务(Transactions)**:对于需要原子性的操作,RabbitMQ 支持 AMQP 协议中的事务模式,确保一系列消息要么全部发送成功,要么全部失败并回滚。 4. **死信队列(Dead Letter Exchange)**:如果消息在长时间内无人消费或者多次重试失败,会被路由到死信队列,这样可以避免无限循环的情况,并提供一种人工干预处理异常的方式。 5. **镜像(Clustering and Mirroring)**:RabbitMQ 集群部署可提供高可用性和故障转移功能,即使某个节点失效,消息也可以被其他节点接管,保证服务不间断。 6. **幂等性(Idempotency)**:RabbitMQ 提供了消息路由和路由键的概念,同一个消息多次投递会产生相同的效果,避免了重复处理。 相关问题-- 1. RabbitMQ如何处理消息丢失的情况? 2. 什么情况下会触发死信队列? 3. 在RabbitMQ集群中,如何实现负载均衡和故障切换?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

未来.....

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

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

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

打赏作者

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

抵扣说明:

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

余额充值