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. 流量控制 ...
随机推荐
- 【原创】大叔经验分享(61)kudu rebalance报错
kudu rebalance命令报错 terminate called after throwing an instance of 'std::regex_error' what(): regex_e ...
- O026、Nova组件详解
参考https://www.cnblogs.com/CloudMan6/p/5436855.html 本节开始,我们将详细讲解 Nova 的各个子服务. 前面架构概览一节知道 Nova 有若干 ...
- SQL语句复习【专题六】
SQL语句复习[专题六] 用户 + 创建表 --创建一个新的用户,然后给新的用户创建一张表,然后给表中添加一些数据.查询表中的数据 --创建用户需要比较大的权限 DBA create user di ...
- Liunx命令问题
第一个问题是:快速杀死服务 第一步:查看进程号pid ps -u my_account -o pid,rss,command | grep redis 第二步:杀死进程 k ...
- windows 环境下基于Python 的GDAL 安装
最近由于需要利用pytho处理地理空间数据,但是python本身并没有访问和处理地理空间数据的包,只能借助于GDAL(Geospatial Data Abstraction Library)来进行访问 ...
- python 时间对应计算
import re import time def parse_time(date): if re.match('刚刚', date): date = time.strftime('%Y-%m-%d ...
- (六) Java数据库
一.概述 程序开发没有数据库的参与,可以说几乎是不可能的.数据库和Java都已经有了简单的了解,现在的关键是对两者进行连接,起到这一作用的正是JDBC——Java Database Connectiv ...
- top命令参数详解
简介 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按 ...
- UnicodeDecodeError: 'utf8' codec can't decode byte 0xc4 in position 0: i报错
在程序的顶部加了下面两行就好了,中文也可以正常显示了 #!/usr/bin/env Python# coding=utf-8
- H5小程序不同页面之间通讯解决方案
小程序做开发的时候难免需要不同页面之间的通讯,比如首页打开新的页面搜索获取结果返回到首页,不同tab页面之间的数据交互等等.于是做了以下总结 打开新的页面可以通过 navigator 组件来实现,通过 ...