基于springboot工程浅谈整合rabbitmq怎么样防止消息发送mq不丢失和消费mq的消息防止丢失
本文只针对springboot整合rabbitmq的消息防丢失,话不多说,上干货....
设置发送mq消息不丢失实现思路
执行的方案:
第一步,要对队列,消息以及交换机进行持久化操作(保存到物理磁盘中)
因为mq消息默认是保存在内存中
交换机我们在声明的时候可以进行持久化
@Bean(EX_BUYING_ADDPOINTUSER)
public Exchange EX_BUYING_ADDPOINTUSER(){
return ExchangeBuilder.directExchange(EX_BUYING_ADDPOINTUSER).durable(true).build();
}
解析:
durable(true)表示对当前交换进行持久化
队列持久化
@Bean
public Queue queue(){
return new Queue(ORDER_TACK);
}
解析:
当前new的过程中如果只有一个参数则表示默认的就是已经持久化了
源码:
public Queue(String name) {
this(name, true, false, false);
}
注意:
消息持久化,不需要设置的,我们的消息是保存在队列中,队列如果说是持久化的,那么我们的消息就是持久化的。
confirm机制
confirm模式需要基于channel进行设置, 一旦某条消息被投递到队列之后,消息队列就会发送一个确认信息给生产者,如果队列与消息是可持久化的, 那么确认消息会等到消息成功写入到磁盘之后发出.
confirm的性能高,主要得益于它是异步的.生产者在将第一条消息发出之后等待确认消息的同时也可以继续发送后续的消息.当确认消息到达之后,就可以通过回调方法处理这条确认消息. 如果MQ服务宕机了,则会返回nack消息. 生产者同样在回调方法中进行后续处理。
思路是把要发送的消息先放一份到redis中 ,当消息发到了交换机exchange中完成就回返回ack为true,那么就完成发送删除redis的消息,否则就从redis取出消息再次发送.直到发送成功....
//增强rabbitmq,代替原来发送消息的一个类,可以防止丢失数据
@Component
public class ConfirmMessageSender implements RabbitTemplate.ConfirmCallback {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate redisTemplate;
public static final String MESSAGE_CONFIRM_KEY="message_confirm_";
//有参构造
public ConfirmMessageSender(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
//rabbitmq设置提交回调
rabbitTemplate.setConfirmCallback(this);
}
//接收消息服务器返回的通知的 ,成功的通知和失败通知,第二步
/**
*
* @param correlationData 用来保证消息的唯一
* @param ack 应答 true表示成功的通知,false失败的通知
* @param cause 原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack){
//成功通知,表示我们数据已经发送成功并且持久化到了磁盘中
//删除redis中的相关数据
redisTemplate.delete(correlationData.getId());
redisTemplate.delete(MESSAGE_CONFIRM_KEY+correlationData.getId());
}else{
//失败通知 ,没有持久化到磁盘中
//从redis中获取刚才的消息内容
Map<String,String> map = (Map<String,String>)redisTemplate.opsForHash().entries(MESSAGE_CONFIRM_KEY+correlationData.getId());
//重新发送
String exchange = map.get("exchange");
String routingkey = map.get("routingKey");
String message = map.get("message");
//再次发送,直到持久化到磁盘为止,每次发送都带着唯一标识
rabbitTemplate.convertAndSend(exchange,routingkey, JSON.toJSONString(message),correlationData);
}
}
//自定义消息发送方法,第一步,当执行该方法的之后,去调用confirm
public void sendMessage(String exchange,String routingKey,String message){
/**
* 重点是 CorrelationData 对象,每个发送的消息都需要配备一个 CorrelationData 相关数据对象,CorrelationData 对象内部只有一个 id 属性,用来表示当前消息唯一性。
*/
//设置消息的唯一标识并存入到redis中
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
//把消息缓存到redis中 ,目的是备份
redisTemplate.opsForValue().set(correlationData.getId(),message);
//将本次发送消息的相关元数据保存到redis中
Map<String,String> map = new HashMap<>();
map.put("exchange",exchange);
map.put("routingKey",routingKey);
map.put("message",message);
//把元数据缓存到redis中,保证消息的唯一
redisTemplate.opsForHash().putAll(MESSAGE_CONFIRM_KEY+correlationData.getId(),map);
//携带着本次消息的唯一标识,进行数据发送
rabbitTemplate.convertAndSend(exchange,routingKey,message,correlationData);
}
}
获取获取mq中的消息不丢失?
在application.yml中设置手动应答:
rabbitmq:
host: 192.168.200.128
listener:
simple:
acknowledge-mode: manual #手动
在监听类中设置手动应答:
简单来说就是当业务逻辑处理没问题就执行channel.basicAck的方法,来返回消费完成,如果出现问题了 就执行channel.basicNack的方法,消息会回到原有的队列,重新的发送,一直到消息发送业务逻辑执行成功
@Component
public class ConsumeListener {
@RabbitListener(queues = RabbitMQConfig.SECKILL_ORDER_KEY)
public void receiveSecKillOrderMessage(Channel channel, Message message){
try {
.....逻辑处理........
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
} catch (IOException e) {
e.printStackTrace();
//返回失败通知
//第一个boolean true所有消费者都会拒绝这个消息,false代表只有当前消费者拒绝
//第二个boolean false当前消息会进入到死信队列,true重新回到原有队列中,默认回到头部
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
} catch (IOException e) {
e.printStackTrace();
}
}
}
流量削峰:保证在同一时间内流量进行削弱,然后放行过来
在监听类中设置:
channel.basicQos(300);
这个300是官方给出的值,代表每次在mq中抓取300个消息消费,
太大会影响服务器的性能,太小就回浪费
希望对大家有帮助...
基于springboot工程浅谈整合rabbitmq怎么样防止消息发送mq不丢失和消费mq的消息防止丢失的更多相关文章
- Python 基于python+mysql浅谈redis缓存设计与数据库关联数据处理
基于python+mysql浅谈redis缓存设计与数据库关联数据处理 by:授客 QQ:1033553122 测试环境 redis-3.0.7 CentOS 6.5-x86_64 python 3 ...
- springboot开发浅谈 2021/05/11
学习了这么久,本人希望有时间能分享一下,这才写下这篇浅谈,谈谈软件,散散心情. 这是本人的博客园账号,欢迎关注,一起学习. 一开始学习springboot,看了好多网站,搜了好多课程.零零落落学了一些 ...
- 浅谈对RabbitMQ的认识
一.什么是消息队列?什么时候使用它? 在传统的web架构中(此处特指Java SSM架构),用户在web中进行了某项需要和后台产生交互的操作后,一般都要开启一个session,从view层开始,由co ...
- springboot整合rabbitmq,支持消息确认机制
安装 推荐一篇博客https://blog.csdn.net/zhuzhezhuzhe1/article/details/80464291 项目结构 POM.XML <?xml version= ...
- 【Java】SpringBoot整合RabbitMQ
介绍 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,AMQP,即A ...
- 浅谈Windows API编程
WinSDK是编程中的传统难点,个人写的WinAPI程序也不少了,其实之所以难就难在每个调用的API都包含着Windows这个操作系统的潜规则或者是windows内部的运行机制…… WinSDK是编程 ...
- RabbitMQ:消息发送确认 与 消息接收确认(ACK)
默认情况下如果一个 Message 被消费者所正确接收则会被从 Queue 中移除 如果一个 Queue 没被任何消费者订阅,那么这个 Queue 中的消息会被 Cache(缓存),当有消费者订阅时则 ...
- 基于springboot整合的rabbitmq
技术:springboot1.5.2 + maven3.0.5 + rabbitmq3.7.13 + jdk1.8 概述 RabbitMQ是对高级消息队列协议(Advanced Message Q ...
- 浅谈Mybatis持久化框架在Spring、SSM、SpringBoot整合的演进及简化过程
前言 最近开始了SpringBoot相关知识的学习,作为为目前比较流行.用的比较广的Spring框架,是每一个Java学习者及从业者都会接触到一个知识点.作为Spring框架项目,肯定少不了与数据库持 ...
随机推荐
- Python协程之asyncio
asyncio 是 Python 中的异步IO库,用来编写并发协程,适用于IO阻塞且需要大量并发的场景,例如爬虫.文件读写. asyncio 在 Python3.4 被引入,经过几个版本的迭代,特性. ...
- js判断传递参数的的类型,并返回
function type(target) { var templet ={ "[object Array]" : "arry"; "[obj ...
- [ASP.NET Core开发实战]基础篇02 依赖注入
ASP.NET Core的底层机制之一是依赖注入(DI)设计模式,因此要好好掌握依赖注入的用法. 什么是依赖注入 我们看一下下面的例子: public class MyDependency { pub ...
- Java实现文件夹下文件实时监控
一.commons-io方法 1.使用Commons-io的monitor下的相关类可以处理对文件进行监控,它采用的是观察者模式来实现的 (1)可以监控文件夹的创建.删除和修改 (2)可以监控文件的创 ...
- Explain Plan试分析
注:以下是本人对Explain Plan的试分析,有不对的地方希望大家指出.关于如何查看Oracle的解释计划请参考:https://www.cnblogs.com/xiandedanteng/p/1 ...
- Java使用ArrayList实现“群主发红包”功能
群主发普通红包,某群有多名成员,群主给成员发普通红包,普通红包的规则: 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取: 成员领取红包后,保存到成员余额中. 请根据描述,完成案例中所有类 ...
- Typora第一次使用
一级标题 二级标题 三级标题 三个# + 空格 分割线 三个- 三个* 粗体 ctrl + B 斜体 ctrl + I 删除线 引用 一个大于号就可以了 图片: ! + [] + (图片路径) 超链接 ...
- 备忘录:SQL SERVER2014 出现:“Cannot find one or more components”
目录 1. 起因 2. 解决方案 3. 备注 4. 参考 2020年9月13日 00:40:09-shanzm 1. 起因 因为卸载vs2015的时候,使用了一个VS2013/2015卸载工具Tota ...
- 乔悟空-CTF-i春秋-Web-Upload
2020.09.03 ai 做过的题,两天不看就忘了-- 做题 题目 题目地址 thinking-- 打开网站 告诉了文件在flag.php中,所以写个php,把flag.php文件读取出来就行 盗来 ...
- 人人框架renren-security |小记(第一篇)
一丶首先介绍一下人人框架: 1.简介 renren-security | 轻量级权限管理系统 采用Spring.MyBatis.Shiro框架,开发的一套权限系统,极低门槛,拿来即用 支持分布式部 ...