rabbitmq保证消息投递成功的对比分析

RabbitMQ(三)-消息可靠性投递 在中,通过工作原理图,我们了解到一个消息从产生到投递成功要经过的几个环节。同样,保证这几个环节的成功执行也是保证消息可靠投递的重要因素。 阅读详情
  • pom.xml

引入rabbitmq所需jar包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>fun.gosuncn</groupId>
    <artifactId>rabbitmq</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.10.0</version>
        </dependency>
    </dependencies>

</project>
  • RabbitmqUtils

设置连接信息,获取连接工厂。

import com.rabbitmq.client.ConnectionFactory;

public class RabbitmqUtils {
    public static ConnectionFactory getConnectionFactory() {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("10.0.8.6");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");
        return factory;
    }
}
  • Receiver

作为消费者不断的监听队列,消费消息。

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class Receiver {
    public static void main(String[] args) {
        ConnectionFactory factory = RabbitmqUtils.getConnectionFactory();
        try {
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
            channel.queueDeclare("direct-queue", false, false, false, null);
            channel.basicConsume("direct-queue", true, (consumerTag, message) -> {
                System.out.println("DeliverCallback's consumerTag is {" + consumerTag + "}");
                System.out.println("消费消息的内容 = " + new String(message.getBody()));
            }, consumerTag -> System.out.println("CancelCallback's consumerTag is {" + consumerTag + "}"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 第一种方式 - 事务方式
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Sender {
    public static void main(String[] args) {
        ConnectionFactory factory = RabbitmqUtils.getConnectionFactory();
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection();
            channel = connection.createChannel();
            channel.queueDeclare("direct-queue", false, false, false, null);
            channel.txSelect();
            channel.basicPublish("", "direct-queue", null, "hello world".getBytes());
            //int i = 1 / 0;
            channel.txCommit();
        } catch (Exception e) {
            if (channel != null) {
                try {
                    channel.txRollback();
                    // TODO 事务回滚 逻辑 [再次发送、存库操作等]
                    System.out.println("事务回滚 逻辑 [再次发送、存库操作等]");
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
            e.printStackTrace();
        } finally {
            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException | TimeoutException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

开启事务channel.txSelect();。

执行channel.basicPublish("", "direct-queue", null, "hello world".getBytes());消息的投递。

使用int i = 1 / 0;模拟上一步消息的投递过程发生了IO异常,此时将不会执行channel.txCommit();操作。

而是进入channel.txRollback();代码块,进行事务回滚逻辑操作。

假如,没有发生任何异常,将会执行channel.txCommit();操作。

以上过程是如何确认消息的投递成功的呢?

首先,客户端开启了事务,客户端将消息投递给服务器,假如投递过程中因网络等原因发生了IOException,那么将会进入channel.txRollback();逻辑;假如投递到服务器了,后续的逻辑发生异常,进入channel.txRollback();依然是属于投递失败,消费者是消费不到消息的。

因此,事务的方式可以处理消息发送失败后的解决方案,以确保对消息的完全掌控。

  • 第二种方式 - 同步confirm方式
package fun.gosuncn.test1;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Sender {
    public static void main(String[] args) {
        ConnectionFactory factory = RabbitmqUtils.getConnectionFactory();
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection();
            channel = connection.createChannel();
            channel.queueDeclare("direct-queue", false, false, false, null);
            channel.confirmSelect();
            channel.basicPublish("", "direct-queue", null, "hello world".getBytes());
            //int i = 1 / 0;
            if (channel.waitForConfirms()) {
                System.out.println("消息已经确认投递成功");
                Thread.sleep(3000L);
            }
            System.out.println("验证waitForConfirms是阻塞方法");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException | TimeoutException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

通过channel.confirmSelect();开启confirm模式。

而channel.waitForConfirms()的作用是,阻塞程序,等待确认结果的返回,进行逻辑操作。

假如channel.basicPublish与channel.waitForConfirms()之间出现了任何异常错误,消息是有可能投递成功的。

  • 第三种方式 - 同步confirm方式(批量)
package fun.gosuncn.test1;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Sender {
    public static void main(String[] args) {
        ConnectionFactory factory = RabbitmqUtils.getConnectionFactory();
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection();
            channel = connection.createChannel();
            channel.queueDeclare("direct-queue", false, false, false, null);
            channel.confirmSelect();
            channel.basicPublish("", "direct-queue", null, "hello world1".getBytes());
            channel.basicPublish("", "direct-queue", null, "hello world2".getBytes());
            channel.basicPublish("", "direct-queue", null, "hello world3".getBytes());
            if (channel.waitForConfirms()) {
                System.out.println("消息已经确认投递成功");
                Thread.sleep(3000L);
            }
            System.out.println("验证waitForConfirms是阻塞方法");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException | TimeoutException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

其实,批量确认和串行确认的区别就是,批量确认是执行多个basicPublish后,执行一次waitForConfirms即可。

  • 第四种方式 - 异步confirm方式
package fun.gosuncn.test1;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConfirmListener;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;

public class Sender {
    public static void main(String[] args) {
        ConnectionFactory factory = RabbitmqUtils.getConnectionFactory();
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection();
            channel = connection.createChannel();
            channel.queueDeclare("direct-queue", false, false, false, null);
            channel.confirmSelect();
            channel.addConfirmListener(new ConfirmListener() {
                public void handleAck(long deliveryTag, boolean multiple) throws IOException {
                    System.out.println("ack:deliveryTag:" + deliveryTag + ",multiple:" + multiple);
                }

                public void handleNack(long deliveryTag, boolean multiple) throws IOException {
                    System.out.println("nack:deliveryTag:" + deliveryTag + ",multiple:" + multiple);
                }
            });
            channel.basicPublish("", "direct-queue", null, "hello world1".getBytes());
            channel.basicPublish("", "direct-queue", null, "hello world2".getBytes());
            channel.basicPublish("", "direct-queue", null, "hello world3".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
//        finally {
//            if (channel != null) {
//                try {
//                    channel.close();
//                } catch (IOException | TimeoutException e) {
//                    e.printStackTrace();
//                }
//            }
//            if (connection != null) {
//                try {
//                    connection.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }
    }
}

使用异步确认的方式需要注意的是:一定不能关闭连接,否则可能会出现异常。

事务方式:42891毫秒

串行确认:40551毫秒

批量确认:688毫秒

异步确认:318毫秒

综上结果,可以看出:事务方式效率最慢,异步确认方式效率最佳。

RabbitMQ系列教程五:RabbitMQ如何保证消息的可靠投递 介绍 一个消息往往会经历如下几个阶段 所以要保证消息的可靠投递,只需要保证这3个阶段的可靠投递即可 生产阶段 这个阶段的可靠投递主要靠ConfirmListener(发布者确认)和ReturnListener(失败通知) 前面已经介绍过了,一条消息在RabbitMQ中的流转过程为 producer -> rabbitmq broker cluster -> exchange -> queue -> consumer ConfirmListener可以获取消息是否从producer. 阅读详情

相关推荐

交换机基本介绍(分类、性能指标、硬件构成及工作方式)

一、交换机的分类与性能指标 1.1交换机的分类 按照网络构成方式来分的话,交换机分为三类:接入层交换机、汇聚层交换机和核心层交换机。 按照OSI模型来划分的话,分为:二层交换机、三层交换机和四层交换机 还有一种按照硬件形态来划分,可以分成两类:盒式交换机和机框式交换机。 盒式交换机是一种有固定端口数,有时也会带有少量扩展槽的交换机。机架式交换机是一种插槽式的交换机,这种交换机扩展性较好,可支持不同的网络类型,可支持更大端口密度的网络。一般在数据中心的接入层都会采用盒式交换机,盒式...

monologuezjp的博客 4万+

RabbitMQ的事务

事务消息与数据库的事务类似,只是MQ中的消息是要保证消息是否全部发送成功,防止丢失消息的一种策略。 RabbitMQ有两种的方式来解决这个问题: 1、通过AMQP提供的事务机制实现 2、使用发送者确认模式实现 开启事务 /**启动事务,启动事务以后所有写入队列 * 中的消息,必须显示调用事务的txCommit()函数 * 来提交事务获取txRollback()回滚事务 * */ /**开启事务 * */ channel.txSelect(); 提交事务 /**提交事 * */ channel.txC.

weixin_43730516的博客 8784

数据库:关系运算整理大全(包括关系代数、元组关系演算、域关系演算)

数据库关系运算: 1. 关系代数(基本关系代数、附加关系代数、扩展关系代数) 2. 元组关系演算 3. 域关系演算

ysji's blog 1万+

rabbitmq 手动提交_RabbitMQ系列(四)RabbitMQ事务和Confirm发送方消息确认——深入解读 - 王磊的博客 - 博客园...

RabbitMQ事务和Confirm发送方消息确认——深入解读RabbitMQ系列文章引言根据前面的知识( 深入了解RabbitMQ工作原理及简单使用 、 Rabbit的几种工作模式介绍与实践 )我们知道,如果要保证消息的可靠性,需要对消息进行持久化处理,然而消息持久化除了需要代码的设置之外,还有一个重要步骤是至关重要的,那就是保证你的消息顺利进入Broker(◇◇),如图所示: 正常情况下,如果...

weixin_39860280的博客 357

Ansys-结构动力学分析-圆柱斜齿轮模态分析学习心得

模态分析的步骤基本一直,不同点在于选择什么单元类型,模型,节点约束等 圆柱斜齿轮模态分析的难点在于圆柱斜齿轮的模型建立,和所要约束的节点的选择。 用命令流方法建立齿轮模型效率较高,当然,在ansys里建立复杂的模型实在不敢恭维,对于自下而上建模,需要知道每个关键点的坐标位置。下图是创建圆柱斜齿轮模型的命令流方式。 模型不同使用的数据也就不同了。 对于施加约束的问题这就必须要熟悉select e...

weixin_45385183的博客 1831

读懂 403 Forbidden, the request has been blocked by UCON.:它不是浏览器渲染问题,而是后端安全闸门在拦截

摘要 403 Forbidden 错误表明服务器理解请求但拒绝执行,通常与权限或访问控制有关。当错误信息显示 "blocked by UCON" 时,说明请求被 SAP 体系中的统一连接管控框架拦截。UCON 采用白名单机制限制外部调用,通过记录、评估、强制三阶段流程实施管控。常见触发场景包括 HTTP 服务与通信场景配置不一致、白名单未更新等。排查时应通过 DevTools 确认服务器响应,使用 curl 排除浏览器干扰,并比较不同环境的行为差异。解决方案通常涉及调整配置传输顺序或更新

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 239

RabbitMQ中的事务与confirmSelect模式

好久没写技术文章了,由于公司马上要做消息相关的业务,所以最近在Docker上搭了一台RabbitMQ并研究研究。 从网易蜂巢上拉取的镜像: docker pull hub.c.163.com/library/rabbitmq:latest 启动容器: docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672...

nuoWei_SenLin的博客 1万+

车载软件架构 —— AUTOSAR Vector SIP包(三)

### 上一篇文章中介绍了AUTOSAR基础软件供应商Vector公司的开发工具链,本文将继续介绍Vector公司的AUTOSAR产品。 ### -> 1、Vector SIP包中的StartApplication ### -> 2、StartApplication如何开始使用

Soly_kun的博客 828

RabbitMQ高级特性(二):RabbitMQ事务(概述)

RabbitMQ高级特性(三):RabbitMQ事务(概述) RabbitMQ支持事务(transaction),RabbitMQ中与事务机制有关的方法有三个:txSelect(), txCommit()以及txRollback()。 (1)txSelect用于将当前channel设置成transaction模式,通过调用tx.select方法开启事务模式。 (2)txCommit用于提交事务。当开启了事务模式后,只有当一个消息被所有的镜像队列保存完毕后,RabbitMQ才会调用tx.commit-ok

HaleyTiger的博客 3012

AI Agent开发第84课-paddleocr-vl全网唯一最全本地化布署教程

本文详解 PaddleOCR-VL 本地化布署全过程,指出为何在真实生产环境中 PaddleOCR-VL 更稳定、更易部署、更贴近工程落地。同时还会详细比较与 DeepSeek-OCR 的核心差异,为全网独家介绍paddleocr-vl的本地部署实战指南。

打造全国最全的AI Agent开发知识领域的博客 5966

从 SM30 到 Fiori:在 SAP BTP ABAP Environment 里创建 Business Configuration 配置维护对象的完整路径

摘要 在SAP BTP的ABAP环境中,传统SAP GUI和SM30配置方式被Business Configuration (BC)替代。BC通过Fiori应用维护配置,支持传输和权限控制。配置表需满足可维护性条件,如允许数据维护、包含技术字段等。通过ADT生成Maintenance Object和Transport Object,实现配置发布与治理。权限管理需创建IAM App和Business Catalog,确保配置可维护。BC在云端延续了可控、可追溯、可发布的治理原则。 (字数:150)

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 242

分布式异步队列学习总结10(消息确认)

rabbitmq服务在运行时,如何确保生产者发送的消息一定能够进入到消息队列中,这时候就需要引入消息确认机制。消息确认机制就是在rabbitmq接收到消息时对生产者进行一个反馈,告诉生产者,你发送给我的消息,我已经收到;同理,消费者也有相关的消息确认机制,确保rabbitmq队列中的消息能够被消费者消费。消息确认机制流程图如下所示: 第一种情况,生产者接收来自rabbitmq的反馈。确保生产者发送的消息有被接收到。 生产端消息确认的两种模式: 1.Confirm模式 应答模式,生产.

每天学习一点点 615

简谈基于FPGA的千兆以太网设计

简谈基于FPGA的千兆以太网设计 今天给大侠带来简谈基于FPGA的千兆以太网设计,话不多说,上货。 今天我们来简单的聊一聊以太网,以太网在FPGA学习中属于比较高级的内容了,有些大侠肯定会感觉以太网学习起来非常不容易。其实,我可以告诉大家,前期学习的基础打扎实了,后期的学习也没那么难。总之就是说难没那么难,说容易也不是那么容易。那么,言归正传,下面让我们一起来聊一聊以太网的学习。 说起以太网,大家可能就会想到百兆以太网、千兆以太网以及万兆以太网等等。局域以太网从10M开始发展,经历几多的变迁,发展到现

3620

中间件——(二)rabbitMQ的相关知识点及概念

rabbitMQ的相关知识点及概念 文章目录rabbitMQ的相关知识点及概念【一】几种流行的中间件介绍【二】RabbitMQ高性能的原因【三】AMQP协议的核心概念【四】RabbitMQ的命名行,管控台【五】Exchange和路由Key【六】保证信息100%投递成功【七】幂等性【八】RabbitMQ的主要作用【九】链接 【一】几种流行的中间件介绍 当前使用较多的消息队列有RabbitMQ、Roc...

wenge1477的博客 325

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

消息可靠投递实践:如何保证 RabbitMQ 的消息可靠投递

死信队列”其实就是一个普通的 RabbitMQ 队列,我们可以在创建一个队列的时候为它指定 x-dead-letter-exchange 和 x-dead-letter-routing-key 参数,这样当这个队列中的消息因为各种原因被拒绝,并且设置的是不重新入队,那么 RabbitMQ 就会自动地将这个消息重新发布到我们指定的 exchange,并且用我们指定的 routing key 进行路由,从而实现消息的“死信”处理。在每次消费者准备处理消息的时候,我们都检查 "retry_count" 的值。

pengyi123的博客 1731

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

RabbitMQ如何保证消息的可靠性投递

RabbitMQ如何保证消息的可靠性投递 目前来说,现在有两种方案实施: 1.数据库持久化方案 2.消息延迟投递方案 数据库持久化方案 流程: 1.将业务订单数据和生成的Message进行持久化操作(一般情况下插入数据库,这里如果分库的话可能涉及到分布式事务) 2.将Message发送到Broker服务器中 3.通过RabbitMQ的Confirm机制,在producer端,监听服务器是否A...

qq_18483301的博客 3173

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

SpringBoot+RabbitMQ (保证消息100%投递成功并被消费)

作者:wangzaiplus来源:jianshu.com/p/dca01aad6bc8一、先扔一张图说明:本文涵盖了关于RabbitMQ很多方面的知识点...

Java 架构师之路 4699

RabbitMQ如何保证消息投递

本文是Java中RabbitMQ的使用指南,涵盖安装、配置及在电商场景下的应用,代码实现。其中详细介绍了订单服务的SQL建表语句,包括订单表、业务消息表和业务日志表的创建,以及订单服务所需导入的依赖。

qq_57967904的博客 1080

RabbitMQ如何保证发送的消息可靠(重要)

RabbitMQ如何保证发送的消息可靠(RabbitMQ的Confirm模式和2.Return模式)

qq_46112274的博客 2352

【RabbitMQ】如何保证消息可靠性投递?

RabbitMQ的可靠性投递 RabbitMQ的可靠性投递,也就是在使用RabbitMQ实现异步通信的时候,消息丢了怎么办,消息重复消费怎么办?在RabbitMQ里面提供了很多保证消息可靠投递的机制,这个也是RabbitMQ的一个特性。 在说可靠性投递的时候,必须要明确一个问题,因为效率与可靠性是无法兼得的,如果要保证每一个环节都成功,势必会对消息的收发效率造成影响。所以如果是一些业务实时一致性要求不是特别高的场合,可以牺牲一些可靠性来换取效率。比如发送通知或者记录日志的这种场景,如果用户没有收到通知,不会

A minor 1407

RabbitMQ保证消息的可靠投递,Java实现RabbitMQ消息的可靠投递,Springboot实现RabbitMQ消息的可靠投递

title . put("desc" , "新增商户");return k;如果先发MQ的话,如果入库失败,就会导致MQ消息无法回滚了。今天我们就好好聊一聊RabbitMQ消息可靠投递的问题。

秃了也弱了 2331

RabbitMQ消息可靠性投递和消息的百分百成功投递

RabbitMQ消息的可靠性传递(三种故障应对)

weixin_52634451的博客 1244

RabbitMQ如何保证消息发送、消费成功

rabbitmq如何保证消息被消费成功

草原孤狼的专栏 9319

RabbitMQ生产端保证消息100%投递成功

文章目录什么是生产端的可靠性投递互联网大厂生产端可靠性投递方案消息落库对消息状态进行打标消息的延迟投递,做二次检查,回调确认 什么是生产端的可靠性投递 保证消息成功发出 保证MQ节点的成功接收 发送端收到MQ节点(borker)的确认应答 完善的消息补偿机制 互联网大厂生产端可靠性投递方案 消息落库对消息状态进行打标 生产者将业务数据和消息入库,并设置信息状态为0,即初始待投递 生产者将消...

Windsor24的博客 404

RabbitMQ消息100%可靠性投递的解决方案实现(一)

RabbitMQ消息中间件极速入门与实战 课程 RabbitMQ学习——高级特性 RabbitMQ消息中间件技术精讲(三)—— 深入RabbitMQ高级特性 https://blog.youkuaiyun.com/u012211603/article/details/86118129 消息如何保证100%投递成功 什么是生产端的可靠性投递 保障消息的成功发出 保障MQ节点的成功接收 发送端收到MQ节点(Br...

eluanshi12的博客 7278

RabbitMQ实现可靠性消息投递---保证消费者接收到消息

一、保证可靠性消息投递 首先需要明确,效率与可靠性是无法兼得的,如果要保证每一个环节都成功,势必会对消息的收发效率造成影响。 如果是一些业务实时一致性要求不是特别高的场合,可以牺牲一些可靠性来换取效率。 在消息投递过程中,一共有四处需要保证可靠性。如图。 ①代表消息从生产者发送到Exchange; ②代表消息从Exchange路由到Queue; ③代表消息在Queue中存储; ④代表消费者订阅...

逆流而上的博客 7503
上一篇: 使用POI将数据库中的数据导入到Excel中
下一篇: rabbitmq中confirm和return模式的使用
盖了帽
博客等级 码龄8年 17粉丝 62原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值