RabbitMQ消息模式

1、消息如何保证100%的投递?

什么是生产端的可靠性投递?
保障消息的成功发出
保障MQ节点的成功接收
发送端收到MQ节点(Broker)确认应答
完善的消息进行补偿机制

BAT/TMD互联网公司的解决方案:
消息落库,对消息状态进行打标
消息的延迟投递,做二次确认,回调检查

消息落库步骤:
1、生产者将业务数据和消息入库,并设置信息状态为0,即初始待投递
2、生产者将消息发送至broker
3、broker向生产者发送确认
4、生产者收到broker确认后修改消息状态为1,即消息投递成功
5、系统定时任务扫描未投递成功的消息
6、生产者将为成功投递的消息重发给broker,并记录重发次数
7、当重发次数大于3时,此时修改消息状态为2,即投递失败。对于投递失败的消息启用补偿机制或人工去处理失败消息

在这里插入图片描述
2. 消息的延迟投递,做二次确认,回调检查
在这里插入图片描述
流程步骤:
第1步:首先业务数据落库,成功才后第一次消息发送
第2步:紧着着发送第2条消息(可以用于寻找第1条消息),用于延迟(可能2,3分钟后才发送)消息投递检查
第3步:Broker端收到消息后,消费端进行消息处理
第4步:处理成功后,发送confirm消息
第5步:收到confirm消息后,将消息进行持久化存储
第6步:收到了delay消息,检查DB数据库,若对应的第1条消息已处理完成,则不做任何事情;若收到了delay消息,检查DB数据库,发现对应的第1条消息处理失败(或无记录),则发送重传命令到上游服务,循环第1步

2、幂等性概念

HTTP/1.1中对幂等性的定义是:一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。

Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.

这里需要关注几个重点:

幂等不仅仅只是一次(或多次)请求对资源没有副作用(比如查询数据库操作,没有增删改,因此没有对数据库有任何影响)。

幂等还包括第一次请求的时候对资源产生了副作用,但是以后的多次请求都不会再对资源产生副作用。

幂等关注的是以后的多次请求是否对资源产生的副作用,而不关注结果。

网络超时等问题,不是幂等的讨论范围。

幂等性是系统服务对外一种承诺(而不是实现),承诺只要调用接口成功,外部多次调用对系统的影响是一致的。声明为幂等的服务会认为外部调用失败是常态,并且失败之后必然会有重试。

什么情况下需要幂等
业务开发中,经常会遇到重复提交的情况,无论是由于网络问题无法收到请求结果而重新发起请求,或是前端的操作抖动而造成重复提交情况。 在交易系统,支付系统这种重复提交造成的问题有尤其明显,比如:

用户在APP上连续点击了多次提交订单,后台应该只产生一个订单;

向支付宝发起支付请求,由于网络问题或系统BUG重发,支付宝应该只扣一次钱。 很显然,声明幂等的服务认为,外部调用者会存在多次调用的情况,为了防止外部多次调用对系统数据状态的发生多次改变,将服务设计成幂等。
业界主流的幂等性操作
唯一ID+指纹码机制,利用数据库主键去重
利用Redis的原子性去实现

唯一ID+指纹码 机制
唯一ID+指纹码机制,利用数据库主键去重
Select count(1) from T_order where ID=唯一ID+指纹码
好处:实现简单
坏处:高并发下有数据库写入的性能瓶颈
解决方案:根据ID进行分库分表进行算法路由

利用Redis的原子性去实现
使用Redis进行幂等,需要考虑的问题
第一:我们是否要进行数据落库,如果落库的话,关键解决的问题是数据库和缓存如何做到原子性?
第二:如果不进行落库,那么都存储到缓存中,如何设置定时同步策略?

3、Confirm确认消息

理解Confirm消息确认机制
消息的确认,是指生产者投递消息后,如果Broker收到消息,则会给我们生产者 一个应答。
生产者进行接收应答,用来确定这条消息是否正常的发送到Broker,这种方式也是消息的可靠性投递的核心保障
在这里插入图片描述
如何实现Confirm确认消息?
第一步:在Channel上开启确认模式:channel.confirmSelect()
第二步:在channel上添加监听:addConfirmListener,监听成功和失败的返回结果,根据具体的结果对消息进行重新发送、或记录日志等后续处理!

消费端代码(Consumer )

package com.xyx.rabbitmqapi.confirm;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;


public class Consumer {
   
    public static void main(String[] args) throws Exception {
   
        //1 创建ConnectionFactory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.224.131");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");

        //2 获取C    onnection
        Connection connection = connectionFactory.newConnection();

        //3 通过Connection创建一个新的Channel
        Channel channel = connection.createChannel();

        String exchangeName = "test_confirm_exchange";
        String routingKey = "confirm.#";
        String queueName = "test_confirm_queue";

        //4 声明交换机和队列 然后进行绑定设置, 最后制定路由Key
        channel.exchangeDeclare(exchangeName, "topic", true);
        channel.queueDeclare(queueName, true, false, false, null);
        channel.queueBind(queueName, exchangeName, routingKey);

        //5 创建消费者
        QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
        channel.basicConsume(queueName, true, queueingConsumer);

        while(true){
   
            QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值