消息如何保证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的高级特性的更多相关文章

  1. Rabbitmq之高级特性——百分百投递消息&消息确认模式&消息返回模式实现

    rabbitmq的高级特性: 如何保障消息的百分之百成功? 要满足4个条件:生产方发送出去,消费方接受到消息,发送方接收到消费者的确认信息,完善的消费补偿机制 解决方案,1)消息落库,进行消息状态打标 ...

  2. RabbitMQ的高级特性概念理解

    1.RabbitMQ中的消息如何保障百分之百的投递成功? 答:百分之百的投递成功,方案可以参考下面的2.3. 2.什么是生产者端的可靠性投递? 答:第一步,生产者保障消息的成功发出.第二步,保障Rab ...

  3. Rabbitmq之高级特性——实现消费端限流&NACK重回队列

    如果是高并发下,rabbitmq服务器上收到成千上万条消息,那么当打开消费端时,这些消息必定喷涌而来,导致消费端消费不过来甚至挂掉都有可能. 在非自动确认的模式下,可以采用限流模式,rabbitmq ...

  4. RabbitMQ(二):RabbitMQ高级特性

    RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.作为一名合格的开发者,有必要了解一下相关知识,RabbitMQ(一)已经入门RabbitMQ,本文介绍Rabb ...

  5. 消息中间件——RabbitMQ(七)高级特性全在这里!(上)

    前言 前面我们介绍了RabbitMQ的安装.各大消息中间件的对比.AMQP核心概念.管控台的使用.快速入门RabbitMQ.本章将介绍RabbitMQ的高级特性.分两篇(上/下)进行介绍. 消息如何保 ...

  6. 消息中间件——RabbitMQ(八)高级特性全在这里!(下)

    前言 上一篇消息中间件--RabbitMQ(七)高级特性全在这里!(上)中我们介绍了消息如何保障100%的投递成功?,幂等性概念详解,在海量订单产生的业务高峰期,如何避免消息的重复消费的问题?,Con ...

  7. RabbitMQ的基本使用到高级特性

    简介 继上一篇 CentOS上安装RabbitMQ讲述RabbitMQ具体安装后,这一篇讲述RabbitMQ在C#的使用,这里将从基本用法到高级特性的使用讲述. 前序条件 这里需要增加一个用户,并且设 ...

  8. RabbitMQ实战(三)-高级特性

    0 相关源码 1 你将学到 如何保证消息百分百投递成功 幂等性 如何避免海量订单生成时消息的重复消费 Confirm确认消息.Return返回消息 自定义消费者 消息的ACK与重回队列 限流 TTL ...

  9. 消息队列——RabbitMQ的基本使用及高级特性

    文章目录 一.引言 二.基本使用 1. 简单示例 2. work queue和公平消费消息 3. 交换机 三.高级特性 1. 消息过期 2. 死信队列 3. 延迟队列 4. 优先级队列 5. 流量控制 ...

随机推荐

  1. string库

    Lua字符串库小集 1. 基础字符串函数: 字符串库中有一些函数非常简单,如: 1). string.len(s) 返回字符串s的长度: 2). string.rep(s,n) 返回字符串s重复n次的 ...

  2. js 使用sessionStorage总结与实例

    作用:它只是可以将一部分数据在当前会话中保存下来,刷新页面数据依旧存在.但当页面关闭后,sessionStorage 中的数据就会被清空 sessionStorage的方法setItem存储value ...

  3. swift学习网址

    一.网站: 0.swift学习者资源分享 1.swift苹果官网:Swift - Overview 2.Swiftist: Home - Swiftist 社区 3.swift中文指南 4.一起swi ...

  4. 我要研究一下minio,管理大量的照片

    随着年龄的增长,电脑里的照片越来越多了,管理和浏览也越来越困难了.

  5. JavaJDBC【五、事务】

    概念: 事务(Transaction)作为单个逻辑工作单元执行的一系列操作. 这些操作都是作为一个整体一起向系统提交,要么都执行,要么都不执行. 特点: 原子性:一个完整操作. 一致性:当事务完成时, ...

  6. 如何处理Win10电脑黑屏后出现代码0xc0000225的错误?

    有些Win10系统的用户反映电脑在开机的时候突然变成黑屏,还出现提示0xc0000225的错误代码,不知道该怎么去解决.一般来说,遇到这种情况一般是系统的注册表出现了问题.下面就为大家分享一下相应的解 ...

  7. Migrating authentication of Samba from smbpasswd to tdb

    Was addicted various After you upgrade the OS of old Samba server. Put it also was using a set of 2. ...

  8. 蓝牙App漏洞系列分析之一CVE-2017-0601

    蓝牙App漏洞系列分析之一CVE-2017-0601 0x01 概要 2017年5月的 Android 安全公告修复了我们提交的一个蓝牙提权中危漏洞,这个漏洞尽管简单,但比较有意思,能够使本地恶意 A ...

  9. IPC之mq_sysctl.c源码解读

    // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2007 IBM Corporation * * Author: Cedric ...

  10. Java ==和equals的区别

    首先了解默认equals方法实现代码 public boolean equals(Object obj) { return (this == obj); } 1.== (1)对于基本数据类型的变量,& ...