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. 流量控制 ...
随机推荐
- 使用EF Core 连接远程oracle 不需要安装oracle客户端方法
连接字符串: Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=IP地址(PORT=1521))(CONNECT_DATA=(SERVICE_ ...
- aspose导出数据
注意 aspose合并单元格后设置单元格样式要一格一格的设置 public class InvoiceAsposeExcel { /// <summary> /// 导出数据 /// &l ...
- 【原创】大叔经验分享(62)kudu副本数量
kudu的副本数量是在表上设置,可以通过命令查看 # sudo -u kudu kudu cluster ksck $master ... Summary by table Name | RF | S ...
- STL之Deque的使用方法
STL 中类 stack 实现了一个栈 1)push 能够插入元素 2)pop 移除栈顶元素 使用的时候,需要包含头文件 #include <stack>,stack 被声明如下: nam ...
- Json-server在Vue 2.0中使用--build文件中没有dev-server文件
跟大佬的视频使用json-server模拟后台数据调用,发现build文件中并没有dev-server.js. 新版的vue-cli取消了dev-server.js和dev-client.js 改 ...
- 判断一个数是否为回文数(js)
//判断是否为回文数:若n=1234321,则称n为一回文数 let readline = require("readline-sync"); let newNum = 0; co ...
- 【Zabbix】分布式监控系统Zabbix【二】
一.Zabbix基本操作 1.主机群组.主机.模板.触发器 a.创建主机群组和主机的过程比较简单,不再介绍 b.配置模板: 创建一个模板,将其分组到Template组,添加配置应用: 给应用创建监控项 ...
- [yii\queue\Queue] [10] unknown job (attempt: 1, PID: 31167) is finished with error: yii\base\ErrorException: unserialize(): Error at offset 1922 of 65535 bytes
网上的解决方案: 1. 报错场景:序列化字段中有中文,反序列化时有可能会出现报错. 错误原因:写入和取出数据库的时候,编码不同,中文符号长度不同,序列化中的长度就无法匹配. 解决办法:适合 php 5 ...
- 1、CentOs安装
转载自:代码之美 0.准备工作: 一台没系统的普通电脑u盘一个(大于1G,最小安装的话不超过1G,根据选择系统大小匹配U盘即可)CentOS7.3 iso文件一个UltraISO工具 1.制作U盘 ① ...
- Perl 认识简介
Perl简介 Perl 是 Practical Extraction and Report Language 的缩写,可翻译为 "实用报表提取语言". Perl 是高级.通用.直译 ...