项目中RabbitMQ如何保证消息的可靠性传输

8 篇文章 0 订阅
3 篇文章 0 订阅

一、RabbitMQ如何保证消息的可靠性传输?

1.使用事务消息

通过对信道的设置实现:

//通知服务器开启事务模式,服务端会返回Tx.Select-Ok
channel.txSelect();
//发布消息
channel.basicPublish();
channel.txCommit();
channel.txRollback();

消费者使用事务:

//手动提交ack,以事务提交或回滚为准
autoAck=false;
//不支持事务
autoAck=true;

如果其中任一环节出现问题,就会抛出IOException异常。用户可以拦截异常进行事务回滚,或决定是否重复消息!事务消息会降低RabbitMQ的性能!!!

2.使用消息确认机制

发送方确认:
channel设置为confirm模式,每条消息会被分配一个唯一id。消息投递成功,信道会发送ack给生产者,包含了id,回调ConfirmCallback接口。如果发生错误导致消息丢失,发送nack给生产者,回调ReturnCallback接口。
ack和nack只有一个被触发,且只有一次,属于异步触发,可以继续发送消息。

@Component
@Slf4j
public class MyCallBack implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 注入
     * 直接通过MyCallBack调用confirm方法是调不到的,因为confirm是ConfirmCallback里面的方法,
     * ConfirmCallback是RabbitTemplate内部的接口,所以需要把MyCallBack注入到RabbitTemplate
     */
    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String id = correlationData != null ? correlationData.getId() : "";
        if (ack) {
            log.info("交换机已经收到id为:{}的消息", id);
        } else {
            log.info("交换机还未收到id为:{}的消息,由于原因:{}", id, cause);
        }
    }

	/**
     * 在消息传递的过程中,不可达目的地时,将消息返回给生产者
     * 该方法只有消息传递失败时才会调用
     */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        log.error("消息:{},被交换机:{}退回,退回原因:{},路由key:{}",
        new String(message.getBody()), exchange, replyText, routingKey);
    }

接收方确认:
声明队列时,指定autoAck=false,broker会等待消费者手动返回ack,才会删除消息,否则自动删除!broker的ack没有超时机制,只会判断链接是否断开,如果断开,消息会重新发送。

//消费成功后,是否要自动应答
channel.basicConsume(QUEUE_NAME, false, deliverCallback, cancelCallback);

RabbitMQ如何确保消息的发送和接收?发布确认模式。

二、项目实现流程

保证消息的可靠性传输:

1.发送消息时,将当前消息数据存入数据库,设置投递状态为消息投递中!
2.开启消息确认回调机制,确认成功,更新投递状态为消息投递成功!
3.开启定时任务,重新投递失败的消息,重试超过3次,更新投递状态为投递失败!

幂等性保证:
消息被消费后,将msgId存入redis!当消息再次被消费时,先判断redis中是否已经存在msgId。若存在,则说明消息已被消费过,将不会被允许消费;若不存在,则说明消息从未被消费,会允许被消费。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值