使用RabbitMq做中间件时,生产者如何保证消息不丢失?(基于rabbitTemplate)

使用RabbitMq做中间件时,生产者如何保证消息不丢失?(基于rabbitTemplate)

一. 生产者confirm机制

配置文件中新增

spring.publisher-confirm-type: correlated

这个配置是意思是:
在发送消息时,带上CorrelationData 对象,这样MQ在收到消息后就可以回调我们的服务,从而可以使用CorrelationData.get 以及 CorrelationData.get(time,TimeUnit) 两个方法监听消息妥投。
这两个方法返回是CorrelationData.Confirm,它有个isAck方法:

  1. 如果isAck为true,则表示妥投。
  2. 如果isAck为false,则表示消息未妥投,可能的原因是交换机不存在。
  3. 如果CorrelationData.get(time,TimeUnit) 超时未返回,则可能消息未妥投。当然也可能消息妥投但是回调失败,这个看下面的消息重发。

代码如下:

CorrelationData.Confirm confirm = correlationData.getFuture().get(300L, TimeUnit.SECONDS);
            if(confirm.isAck()){
                log.info("妥投");
            }else{
                log.error("不妥投");
            }

当然,这种同步的监听方式,并不能满足所有场景,rabbitTemplate还提供了异步的监听方式

rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if(ack){
                    log.info("妥投");
                }else{
                    log.error("不妥投");
                }

           }
        });

注意:异步监听如果消息回调失败,是监听不到的。这个看下面的消息重发。

二.消息持久化

上面消息妥投仅仅指的是消息到达RabbitMq的交换机,但是依旧不能保持消息100%不丢失。
因为这个时间消息只是存放于内存中,如果这时rabbitMq的服务宕机,内存中的消息就可以能丢失。
这时就该用上消息持久化。
在定义交换机与队列时,可以手动设置durable来支持消息持久化

	DirectExchange exchange = ExchangeBuilder
                .directExchange(testExchange)
                .durable(true)
                .autoDelete()
                .build();
	Queue queue = QueueBuilder
                .durable(testQueue)
                .autoDelete()
                .build();

当然,消息持久化会导致吞吐量下降,因为rabbitmq需要在持久化完成才回调我们的服务完成confirm操作。

三.消息重发机制

rabbitTemplate可以设置retryTemplate用于重试,不过很遗憾,这个方法只支持消息发送的请求失败时重发,无法用于保证消息不丢失。

生产者发送消息时,我们可以在redis或者数据库中新增一行数据,同时启动定时器轮询这些数据用于监控消息是否妥投。

然而,有种情况也是需要考虑的,那就是消息可能已经妥投,当时但是回调失败。这样会出现一条消息已经发出去了,重试的时候又发了一次。这时,我们就应该通过消息幂等的方式,来保证消息只能被消费一次。

采用雪花算法,为每条消息生成一个唯一的消息ID,每次在消费前判断消息ID是否存在于redis或者数据库中,存在则丢弃消息,不存在则处理消息。(redis直接用setNx,数据库用一个唯一键维护,插入时报错就时已经存在)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值