Rabbitmq的高级特性
消息如何保证100%投递成功?
什么是生产端的可靠性投递?
1.保障消息的成功发出
2.保障MQ节点的成功接收
3.发送端收到MQ节点(Broker)确认应答
4.完善的消息补偿机制
BAT互联网大厂的解决方案?
1.消息落库,对消息状态进行打标
2.消息的延迟投递,做二次确认,回调检查
优点是消息只持久化一次,对于数据量大的场景性能提升很大。
幂等性机制
海量订单如何避免重复消费问题?
消费端实现幂等性,就意味着,即使我们收到多条一样的消息,最后都会得到同样的结果
1.我们可以借鉴数据库乐观锁机制;
2.比如我们执行一条更新数据库的语句
3.update t_reps set count = count - 1,version = version + 1
where version = 1 业界主流的幂等性操作:
1.唯一ID+指纹码机制,利用数据库主键去重
select count(1) from t_order where id =唯一ID+指纹码
好处:实现简单
坏处:高并发下有数据库写入性能瓶颈
解决方案:根据id进行分库分表进行算法路由
2.利用Redis的原子性去实现
使用redis进行幂等,需要考虑的问题
一、我们是否要进行数据入库,关键解决的问题是数据库和缓存如何做到原子性
二、如果不进行入库,都存到缓存中,如何设置定时同步策略
Confirm消息确认机制
1.消息的确认,是指生产者投递消息后,如果broker收到消息,则会给生产者一个应答
2.生产者进行接收应答,用来确定这条消息是否正常的发送到broker,这种方式也是消息的可靠性投递的核心保障
确认机制流程图:
如何实现confirm确认消息?
1.第一步:在channel上开启确认模式:channel.confirmSelect(),
2.第二步:在channel上添加监听:addConfirmListener,监听成功和失败的返回结果,根据具体的结果对消息进行重新发送、或记录日志等后续处理。
创建生产者
package com.dwz.rabbitmq.confirm; import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConfirmListener;
import com.rabbitmq.client.Connection; public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel();
//指定我们的消息投递模式:消息确认模式
channel.confirmSelect(); String exchangeName = "test_confirm_exchange";
String routingkey = "confirm.abc";
String msg = "Hello rabbit confirm message!";
channel.basicPublish(exchangeName, routingkey, null, msg.getBytes());
//添加一个确认监听
channel.addConfirmListener(new ConfirmListener() {
//deliveryTag 消息投递标识, multiple 是否批量
@Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
System.err.println("-------------no ack--------------");
} @Override
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
System.err.println("-------------ack--------------");
}
}); channel.close();
connection.close();
}
}
创建消费者
package com.dwz.rabbitmq.confirm; import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties; public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel(); String exchangeName = "test_confirm_exchange";
String queueName = "test_confirm_queue";
String routingkey = "confirm.#"; channel.exchangeDeclare(exchangeName, "topic", true);
channel.queueDeclare(queueName, true, false, false, null);
channel.queueBind(queueName, exchangeName, routingkey); DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
System.err.println("消费者收到消息:" + new String(body));
}
}; channel.basicConsume(queueName, consumer);
}
}
Return消息机制
1.Return Listener用于处理一些不可路由的消息!
2.我们的消息生产者,通过指定一个Exchange和Routingkey,把消息送达到某一个队列中去,然后我们的消费者监听队列,进行消费处理操作
3.但是在某些情况下,如果我们在发送消息的时候,当前的Exchange不存在或者指定的路由key路由不到,这个时候如果我们需要监听这种
不可达的消息,就要使用Return Listener。
4.Mandatory:如果为true,则监听器会接受到路由不可达的消息,然后进行后续处理,如果为false,那么broker自动删除该消息
return消息机制流程
创建生产者
package com.dwz.rabbitmq.returnListener; import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ReturnListener; public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel(); String exchangeName = "test_return_exchange";
String routingkey = "return.save";
String routingkeyError = "save.abc";
String msg = "Hello rabbit return message!"; channel.addReturnListener(new ReturnListener() {
@Override
public void handleReturn(int replyCode, String replyText, String exchange, String routingKey,
AMQP.BasicProperties properties, byte[] body) throws IOException {
System.err.println("----------handle return-------------");
System.err.println("replyCode:" + replyCode);
System.err.println("replyText:" + replyText);
System.err.println("exchange:" + exchange);
System.err.println("routingKey:" + routingKey);
System.err.println("properties:" + properties);
System.err.println("body:" + new String(body));
}
});
channel.basicPublish(exchangeName, routingkeyError, true, false, null, msg.getBytes());
}
}
创建消费者
package com.dwz.rabbitmq.returnListener; import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties; public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel(); String exchangeName = "test_return_exchange";
String routingkey = "return.#";
String queueName = "test_return_queue"; channel.exchangeDeclare(exchangeName, "topic", true);
channel.queueDeclare(queueName, true, false, false, null);
channel.queueBind(queueName, exchangeName, routingkey); DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
System.err.println("消费者收到消息:" + new String(body));
}
}; channel.basicConsume(queueName, consumer);
}
}
Rabbitmq的高级特性的更多相关文章
- Rabbitmq之高级特性——百分百投递消息&消息确认模式&消息返回模式实现
rabbitmq的高级特性: 如何保障消息的百分之百成功? 要满足4个条件:生产方发送出去,消费方接受到消息,发送方接收到消费者的确认信息,完善的消费补偿机制 解决方案,1)消息落库,进行消息状态打标 ...
- RabbitMQ的高级特性概念理解
1.RabbitMQ中的消息如何保障百分之百的投递成功? 答:百分之百的投递成功,方案可以参考下面的2.3. 2.什么是生产者端的可靠性投递? 答:第一步,生产者保障消息的成功发出.第二步,保障Rab ...
- Rabbitmq之高级特性——实现消费端限流&NACK重回队列
如果是高并发下,rabbitmq服务器上收到成千上万条消息,那么当打开消费端时,这些消息必定喷涌而来,导致消费端消费不过来甚至挂掉都有可能. 在非自动确认的模式下,可以采用限流模式,rabbitmq ...
- RabbitMQ(二):RabbitMQ高级特性
RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.作为一名合格的开发者,有必要了解一下相关知识,RabbitMQ(一)已经入门RabbitMQ,本文介绍Rabb ...
- 消息中间件——RabbitMQ(七)高级特性全在这里!(上)
前言 前面我们介绍了RabbitMQ的安装.各大消息中间件的对比.AMQP核心概念.管控台的使用.快速入门RabbitMQ.本章将介绍RabbitMQ的高级特性.分两篇(上/下)进行介绍. 消息如何保 ...
- 消息中间件——RabbitMQ(八)高级特性全在这里!(下)
前言 上一篇消息中间件--RabbitMQ(七)高级特性全在这里!(上)中我们介绍了消息如何保障100%的投递成功?,幂等性概念详解,在海量订单产生的业务高峰期,如何避免消息的重复消费的问题?,Con ...
- RabbitMQ的基本使用到高级特性
简介 继上一篇 CentOS上安装RabbitMQ讲述RabbitMQ具体安装后,这一篇讲述RabbitMQ在C#的使用,这里将从基本用法到高级特性的使用讲述. 前序条件 这里需要增加一个用户,并且设 ...
- RabbitMQ实战(三)-高级特性
0 相关源码 1 你将学到 如何保证消息百分百投递成功 幂等性 如何避免海量订单生成时消息的重复消费 Confirm确认消息.Return返回消息 自定义消费者 消息的ACK与重回队列 限流 TTL ...
- 消息队列——RabbitMQ的基本使用及高级特性
文章目录 一.引言 二.基本使用 1. 简单示例 2. work queue和公平消费消息 3. 交换机 三.高级特性 1. 消息过期 2. 死信队列 3. 延迟队列 4. 优先级队列 5. 流量控制 ...
随机推荐
- C++入门基础知识(一)
一:关键字 在C语言中,我们已经学习过了很多的关键字,例如:static,struct等,下面展现一下C++中的一些关键字. 二:命名空间 在C/C++中,变量.函数和类都是大量存在的,这些变量.函数 ...
- ipairs与pairs的区别
ipairs 和pairs在lua中都是遍历tbale的函数可是两者有差别 1.pairs遍历table中的全部的key-vale 而ipairs会依据key的数值从1開始加1递增遍历相应的table ...
- mybatis 主键自增异常
org.springframework.jdbc.UncategorizedSQLException: Error getting generated key or setting result t ...
- 题解luoguP2054 BZOJ1965【[AHOI2005]洗牌】
题目链接: https://www.luogu.org/problemnew/show/P2054 https://www.lydsy.com/JudgeOnline/problem.php?id=1 ...
- JavaSE基础知识之继承
一.概述 继承描述的是事物之间的所属关系,这种关系是: is-a 的关系.例如,图中的兔子属于食草动物,食草动物又属于动物.继承可以使多种事物之间形成一种关系体系,让父类更通用,子类更具体. 1.1 ...
- spring AOP的相关术语
连接点:Joinpoint 其实业务层接口的方法 切入点:Pointcut 被增强的是切入点,没被增强是永远都是连接点.连接点不一定是切入点,切入点一定是连接点 通知:Advice 就是指要增强的 ...
- 解决vs code编写python输出中文乱码问题
环境: win7 vscode 1.37.0 插件: python Code Runner 乱码问题: 创建一个python文件,运行如下代码,打印显示乱码.: 解决乱码步骤: Ctrl+Shift+ ...
- video 轮播视频
<video controls :src="product.videoUrl" :poster="resURL + defaultImg">< ...
- 跨平台编译ceres for Android
折腾了几乎一天,记录一下. 最大的坑是官网给出的 1.进入ceres源代码目录下的jni目录 2.EIGEN_PATH="指向eigen库目录,即包含EIGEN文件夹的那个文件夹” ndk- ...
- Windows defender怎么才能彻底关闭?
据不久前的一项测试表明,Windows系统自带的Windows defender软件在所有参与测试的杀毒安全软件中对win10的运行速度影响最大. 而Win10系统的Windows defender会 ...