延迟队列的三种实现方案

news2024/12/26 21:07:31

延迟任务

  • 定时任务:有固定周期的,有明确的触发时间
  • 延迟队列:没有固定的开始时间,它常常是由一个事件触发的,而在这个事件触发之后的一段时间内触发另一个事件,任务可以立即执行,也可以延迟

在这里插入图片描述

应用场景:

场景一:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单;如果期间下单成功,任务取消。

场景二:接口对接出现网络问题,1分钟后重试,如果失败,2分钟重试,直到出现阈值终止。

延迟队列技术

DelayQueue

JDK自带DelayQueue 是一个支持延时获取元素的阻塞队列, 内部采用优先队列 PriorityQueue 存储元素,同时元素必须实现 Delayed 接口;在创建元素时可以指定多久才可以从队列中获取当前元素,只有在延迟期满时才能从队列中提取元素

在这里插入图片描述

RabbitMQ实现延迟任务

  • TTL:Time To Live (消息存活时间)

  • 死信队列:Dead Letter Exchange(死信交换机),当消息成为Dead message后,可以重新发送另一个交换机(死信交换机)

在这里插入图片描述

  • 模拟业务逻辑。

在这里插入图片描述

  • 导入依赖。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--以及SpringBoot Web启动器等依赖-->
  • 配置Yaml文件。
server:
  port: 8006

spring:
  rabbitmq:
    host: 192.168.208.128
    port: 5672
    virtual-host: /
    username: admin
    password: admin
  • 创建交互机与队列。
@Configuration
public class OrderRabbitConfig {


    // 创建下单交换机
    @Bean
    public DirectExchange orderExchange(){
        return new DirectExchange("order.exchange",true,false);
        /*
         * 第二参数:是否持久化,交换机将在服务器重启后继续存在。
         * 第三参数:如果服务器在不再使用交换机时是否删除。
         */
    }


    // 创建延迟队列
    @Bean
    public Queue delayQueue(){
        return QueueBuilder
                .durable("order.queue")
                .ttl(20000) //过期时间,单位毫秒
                .deadLetterExchange("dl.exchange")//指定死信交换机
                .deadLetterRoutingKey("dl.key")//指定死信路由key
                .build();
    }

    // 绑定死信交换机和死信队列
    @Bean
    public Binding bindDelayQueueToExchange(
        DirectExchange orderExchange,
        Queue delayQueue
    ){
        return BindingBuilder.bind(delayQueue).to(orderExchange).with("order.key");
    }



    // 创建死信交换机
    @Bean
    public DirectExchange createDeadLettterExchange(){
        return new DirectExchange("dl.exchange",true,false);
    }

    // 创建死信队列
    @Bean
    public Queue createDeadLettterQueue(){
        return QueueBuilder
                .durable("dl.queue")
                .build();
    }

    // 绑定死信交换机和死信队列
    @Bean
    public Binding bindQueueToExchange(){
        return BindingBuilder
            .bind(createDeadLettterQueue())
            .to(createDeadLettterExchange())
            .with("dl.key");
    }

}
  • 创建监听器消费死信队列。
@Component
public class OrderListener {
    
    @Autowired(require = false)
    private OrderService orderService;

    @RabbitListener(queues = "dl.queue")
    public void handleOrderMsg(String msg){
        System.out.println("处理失效订单:"+new Date());
        //通过msg中的订单ID获取订单对象
        Order order = orderService.getById(Long.parseLong(msg));
        //先判断该订单是否已经支付
        //如果还是未支付,才进行修改(status=5,取消时间更新,把库存还原)
        System.out.println(msg+" = status = 5,取消时间更新,把库存还原)");
    }
}
  • 创建处理请求模拟下单。
@RestController
public class SendMessageController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/sendMsg")
    public String sendMsg(){
        System.out.println("下单时间:"+new Date());
        rabbitTemplate.convertAndSend("order.exchange","order.key","OrderId");
        return "发送成功";
    }

}

redis实现延迟任务

zset数据类型的去重有序(分数排序)特点进行延迟。例如:时间戳作为score进行排序

在这里插入图片描述

  • 引入Redisson依赖。
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.16.3</version>
</dependency>
<!--以及SpringBoot Web使用的依赖-->
  • 配置yaml文件。
server:
  port: 8002
spring:
  application:
    name: redisson-demo
  redis:
    host: 192.168.88.143
    redisson:
      config:
        clusterServersConfig:
          nodeAddresses:
          - "redis://192.168.88.143:6379"
  • 发送延迟任务消息。
@RestController
@RequestMapping("/test")
public class TestController {

    // 注入RedissonClient客户端
    @Autowired
    private RedissonClient client;

    // 发送消息

    @GetMapping("/send/{time}")
    public ResponseEntity send(@PathVariable("time") Long time) {
        // 获取一个阻塞队列  指定队列的名称
        RBlockingQueue<String> blockingQueue = client.getBlockingQueue("test_block");
        // 创建一个延迟队列 指定使用哪个阻塞队列
        RDelayedQueue<String> delayedQueue = client.getDelayedQueue(blockingQueue);
        // 发送延迟消息 指定消息内容  延迟时间  时间单位
        delayedQueue.offer("hello redis", time, TimeUnit.SECONDS);
        return ResponseEntity.ok("发送成功" + new Date());
    }
}
  • 消费消息,执行延迟任务。
@Service
public class MsgListener {

    // 注入RedissonClient客户端
    @Autowired
    private RedissonClient client;

    // 实例化该类时首先执行这个方法
    @PostConstruct 
    public void handleMessage() {
        // 使用线程运行
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 获取一个阻塞队列  指定队列的名称
                RBlockingQueue<String> blockingQueue = 
                    client.getBlockingQueue("test_block");
                // 在监听器启动时先发一条自定义消息,主要是用于激活这个队列
                // 创建一个延迟队列 指定使用哪个阻塞队列
                RDelayedQueue<String> delayedQueue = 
                    client.getDelayedQueue(blockingQueue);
                // 发送延迟消息 指定消息内容  延迟时间  时间单位
                delayedQueue.offer("init", 1, TimeUnit.SECONDS);

                while (true) {
                    String msg = null;
                    try {
                        // 拉取消息 指定超时时间 默认这个方法是阻塞的
                        msg = blockingQueue.poll(10, TimeUnit.SECONDS);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (!StringUtils.isEmpty(msg)) {
                        System.out.println("接收到消息: " + msg + ", " + new Date());
                    }
                }
            }
        }).start();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/600056.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python关联性分析:介绍及应用案例

Python 关联性分析&#xff1a;介绍及应用案例 在数据分析和机器学习领域中&#xff0c;关联性分析是一种经常被使用的工具。通过分析不同特征之间的相关性&#xff0c;可以获取大量有价值的信息&#xff0c;如客户行为模式、产品关联性等等。Python作为一种高效而简洁的编程语…

SpringCloud(2)

服务拆分和远程调用 任何分布式架构都离不开服务的拆分&#xff0c;微服务也是一样。 2.1.服务拆分原则 这里我总结了微服务拆分时的几个原则&#xff1a; 不同微服务&#xff0c;不要重复开发相同业务微服务数据独立&#xff0c;不要访问其它微服务的数据库微服务可以将自…

【生物力学】《人体骨肌系统生物力学》- 王成焘老师 - 第1章 - 总论

目录回到目录第2章 文章目录 1.1 人体骨肌系统1.1.1 人体骨骼系统1. 骨骼的功能2. 骨骼的构造3. 骨组织的构成1. 骨细胞与骨基质2. 成骨细胞3. 破骨细胞4. 骨原细胞 4. 皮质骨与松质骨的构造1. 皮质骨2. 松质骨 1.1.2 关节与骨连接1. 运动关节2. 局部活动关节3. 微动关节与固定…

chatgpt赋能python:Python中点的SEO

Python中点的SEO 在Python编程中&#xff0c;点&#xff08;.&#xff09;是一个非常重要的语法符号&#xff0c;可以用于访问对象属性、调用方法、导入模块等。但是&#xff0c;在SEO优化中&#xff0c;点也有着特殊的含义。 什么是点的SEO含义&#xff1f; 在URL地址中&am…

chatgpt赋能python:Python关联规则代码:优化你的数据分析策略

Python关联规则代码&#xff1a;优化你的数据分析策略 数据分析是当今商业竞争中的重要环节之一。随着数据量的不断增长&#xff0c;为了更好地发现数据之间的关系和规律&#xff0c;数据分析师需要采用一些有效的工具和技术。Python是一种强大的编程语言&#xff0c;可以用于…

白天过节,晚上了解了下 Threejs3D

文章目录 I. 介绍Three.js 3DA. 什么是Three.jsB. Three.js的历史C. Three.js的应用领域 II. 开始使用Three.js 3DA. 安装和引入Three.jsB. 创建Three.js场景C. 添加3D对象到场景D. 控制相机和灯光E. 渲染场景 III. Three.js 3D中的基本概念A. 坐标系统和变换B. 材质和纹理C. 几…

分布式存储Ceph的部署及应用(创建MDS、RBD、RGW 接口)

目录 一、存储基础1.1 单机存储设备1.2 单机存储的问题 二、分布式存储&#xff08;软件定义的存储 SDS&#xff09;2.1 分布式存储的类型 三、Ceph 简介3.1 Ceph 优势3.2 Ceph 架构3.3 Ceph 核心组件3.4 Pool、PG 和 OSD 的关系3.5 OSD 存储后端3.6 Ceph 数据的存储过程3.7 Ce…

音视频基础 及 海思sample_venc解读

1、sample的整体架构 (1)sample其实是很多个例程&#xff0c;所以有很多个main (2)每一个例程面向一个典型应用&#xff0c;common是通用性主体函数&#xff0c;我们只分析venc (3)基本的架构是&#xff1a;venc中的main调用venc中的功能函数&#xff0c;再调用common中的功…

chatgpt赋能python:关于Python关联数组

关于Python关联数组 Python是一种高级编程语言&#xff0c;具有简单、易懂的语法和丰富的功能。其中一项强大的特性是Python关联数组&#xff0c;也称为字典。在本文中&#xff0c;我们将探讨什么是Python关联数组、为什么它们很有用、如何使用它们以及应该使用哪种类型的关联…

了解FFmpeg音频通道布局结构:AVChannelLayout结构体解析

1. 引言&#xff08;Introduction&#xff09; 1.1 FFmpeg简介&#xff08;Brief Introduction to FFmpeg&#xff09; FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。它提供了录制、转换以及流化音视频的完整解决方案。它包含…

计算机网络,期末大题整理part1

1.要发送的数据1010001&#xff0c;采用CRC生成多项式是P(X)X4X2X1&#xff0c;试求应添加在数据后面的余数。 接收端接收到的PPP帧的数据部分是0001110111110111110110&#xff0c;问删除发送端加的零比特后变成怎样的比特串 答&#xff1a;00011101111111111110 &#xff0…

vue3 antd项目实战——修改和增加公用一个弹窗(页面组件传值)

vue3 antd项目实战——修改和增加公用一个弹窗&#xff08;页面组件传值&#xff09; 往期知识调用&#xff08;步骤不懂就看这儿&#xff09;场景复现实战演示基础modal框的搭建现在我们就可以实现modal框及内部表单的动态绑定了&#xff01;&#xff01;&#xff01; ![在这里…

国内可用 ChatGPT 网页版

前言 ChatGPT持续火热&#xff0c;然鹅国内很多人还是不会使用。 2023年6月1日消息&#xff0c;ChatGPT 聊天机器人可以根据用户的输入生成各种各样的文本&#xff0c;包括代码。但是&#xff0c;加拿大魁北克大学的四位研究人员发现&#xff0c;ChatGPT 生成的代码往往存在严…

读改变未来的九大算法笔记01_数据压缩

1. 起源 1.1. 香农–法诺编码&#xff08;Shannon-Fano Coding&#xff09; 1.1.1. 克劳德香农 1.1.1.1. 1948年论文创建信息理论领域的贝尔实验室科学家 1.1.2. 麻省理工学院教授罗伯特法诺&#xff08;Robert Fano&#xff09; 1.2. 霍夫曼编码 1.2.1. 大卫霍夫曼 1.2…

chatgpt赋能python:Python关联图简介

Python关联图简介 Python语言是一种非常流行和广泛使用的语言&#xff0c;可用于各种用途&#xff0c;包括数据分析和数据可视化。在数据可视化方面&#xff0c;Python有许多强大的库和工具&#xff0c;可以用来创建各种类型的图表和图形。其中之一是Python关联图。 在本篇文…

LNMP应用

安装 Nginx 服务 systemctl stop firewalld systemctl disable firewalld setenforce 0 1、安装依赖包 yum -y install pcre-devel zlib-devel gcc gcc-c make2、创建运行用户 useradd -M -s /sbin/nologin nginx3、编译安装 cd /opt tar zxvf nginx-1.12.0.tar.gz -C /op…

chatgpt赋能Python-python关联分析算法

介绍 Python是一种高级、通用、直译式编程语言。在数据科学和机器学习领域&#xff0c;它已成为首选语言之一。它有很多强大的库和框架&#xff0c;可以帮助数据分析师、科学家和工程师处理大量数据。Python关联分析算法就是其中之一。 Python关联分析算法可以帮助我们在数据…

MobileNetv1、MobileNetv2、MobileNetv3网络讲解

MobileNetv1、MobileNetv2、MobileNetv3网络讲解_mobilenetv3和mobilenetv2_I松风水月的博客-CSDN博客MobileNetv1、MobileNetv2、MobileNetv3网络讲解https://blog.csdn.net/qq_38683460/article/details/127409816

ChatGPT工作提效之layedit上传多附件的解决方案(layedit赋值、layui.js底层修改、追加模式多附件上传)

ChatGPT工作提效系列文章目录 ChatGPT工作提效之初探路径独孤九剑遇强则强ChatGPT工作提效之在程序开发中的巧劲和指令(创建MySQL语句、PHP语句、Javascript用法、python的交互)ChatGPT工作提效之生成开发需求和报价单并转为Excel格式ChatGPT工作提效之小鹅通二次开发批量API对…

人体姿态估计与MMPose

姿态估计&#xff1a;从给定的图像中识别人脸、手部、身体等关键点 输入&#xff1a;图像I 输出&#xff1a;所有关键点的像素坐标 2D姿态估计&#xff1a;在图像上定位人体关键点的坐标 基本思路&#xff1a; 1.将关键点检测建模为回归问题&#xff0c;让模型直接回归关键点…