当前位置: 首页 > news >正文

【延时队列的实现方式】

文章目录

  • 延时队列
  • JDK自带的延时队列实现
  • Redis实现延迟队列
  • RabbitMQ 延时队列

延时队列

延时队列是一种特殊类型的队列,它允许元素在特定时间间隔后才能被处理。这种队列在处理具有延迟需求的任务时非常有用,例如定时任务、事件驱动系统等
延时队列在项目中的应用还是比较多的,尤其像电商类平台:
1、订单成功后,在30分钟内没有支付,自动取消订单
2、外卖平台发送订餐通知,下单成功后60s给用户推送短信。
3、如果订单一直处于某一个未完结状态时,及时处理关单,并退还库存
4、淘宝新建商户一个月内还没上传商品信息,将冻结商铺等

JDK自带的延时队列实现

在Java中,DelayQueue 是一个无界阻塞队列,它存放实现了 Delayed 接口的对象,只有在延迟时间到了,对象才能从队列中取出来。DelayQueue 是基于优先队列实现的,队列中的元素按照延迟时间的先后顺序排序。
DelayQueue是一个BlockingQueue(无界阻塞)队列,它本质就是封装了一个PriorityQueue(优先队列),PriorityQueue内部使用完全二叉堆(不知道的自行了解哈)来实现队列元素排序,我们在向DelayQueue队列中添加元素时,会给元素一个Delay(延迟时间)作为排序条件,队列中最小的元素会优先放在队首。队列中的元素只有到了Delay时间才允许从队列中取出。队列中可以放基本数据类型或自定义实体类,在存放基本数据类型时,优先队列中元素默认升序排列,自定义实体类就需要我们根据类属性值比较计算了。

package com.schdule.util;import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;class MyDelayedTask implements Delayed {private long delayTime;public MyDelayedTask(long delayTime) {this.delayTime = delayTime;}@Overridepublic long getDelay(TimeUnit unit) {return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);}@Overridepublic int compareTo(Delayed other) {if (this.delayTime < ((MyDelayedTask) other).delayTime) {return -1;} else if (this.delayTime > ((MyDelayedTask) other).delayTime) {return 1;} else {return 0;}}public static void main(String[] args) throws InterruptedException {DelayQueue<MyDelayedTask> queue = new DelayQueue<>();queue.put(new MyDelayedTask(System.currentTimeMillis() + 5000)); // 5秒后执行while (true) {MyDelayedTask task = queue.take();System.out.println("Executing task at: " + System.currentTimeMillis());}}
}

DelayQueue的put方法是线程安全的,因为put方法内部使用了ReentrantLock锁进行线程同步。DelayQueue还提供了两种出队的方法 poll() 和 take() , poll() 为非阻塞获取,没有到期的元素直接返回null;take() 阻塞方式获取,没有到期的元素线程将会等待。

Redis实现延迟队列

Redis的数据结构Zset,同样可以实现延迟队列的效果,主要利用它的score属性,redis通过score来为集合中的成员进行从小到大的排序。
在这里插入图片描述
Redis有序集合的一些常用命令包括:
ZADD: 向有序集合添加一个或多个成员,或者更新已存在成员的分数。
ZRANGE: 返回有序集合中指定区间内的成员列表。
ZREVRANGE: 返回有序集合中指定区间内的成员列表,按分数从高到低排序。
ZRANGEBYSCORE: 返回有序集合中指定分数区间内的成员列表。
ZREM: 移除有序集合中的一个或多个成员。
ZCARD: 获取有序集合的成员数。
ZSCORE: 获取有序集合中成员的分数。

    /*** 消费消息*/public void pollOrderQueue() {while (true) {Set<Tuple> set = jedis.zrangeWithScores(DELAY_QUEUE, 0, 0);String value = ((Tuple) set.toArray()[0]).getElement();int score = (int) ((Tuple) set.toArray()[0]).getScore();Calendar cal = Calendar.getInstance();int nowSecond = (int) (cal.getTimeInMillis() / 1000);if (nowSecond >= score) {jedis.zrem(DELAY_QUEUE, value);System.out.println(sdf.format(new Date()) + " removed key:" + value);}if (jedis.zcard(DELAY_QUEUE) <= 0) {System.out.println(sdf.format(new Date()) + " zset empty ");return;}Thread.sleep(1000);}}

RabbitMQ 延时队列

利用 RabbitMQ 做延时队列是比较常见的一种方式,而实际上RabbitMQ 自身并没有直接支持提供延迟队列功能,而是通过 RabbitMQ 消息队列的 TTL和 DXL这两个属性间接实现的。
先来认识一下 TTL和 DXL两个概念:
Time To Live(TTL) :
TTL 顾名思义:指的是消息的存活时间,RabbitMQ可以通过x-message-tt参数来设置指定Queue(队列)和 Message(消息)上消息的存活时间,它的值是一个非负整数,单位为微秒。
RabbitMQ 可以从两种维度设置消息过期时间,分别是队列和消息本身
设置队列过期时间,那么队列中所有消息都具有相同的过期时间。
设置消息过期时间,对队列中的某一条消息设置过期时间,每条消息TTL都可以不同。
如果同时设置队列和队列中消息的TTL,则TTL值以两者中较小的值为准。而队列中的消息存在队列中的时间,一旦超过TTL过期时间则成为Dead Letter(死信)。
Dead Letter Exchanges(DLX)
DLX即死信交换机,绑定在死信交换机上的即死信队列。RabbitMQ的 Queue(队列)可以配置两个参数x-dead-letter-exchange 和 x-dead-letter-routing-key(可选),一旦队列内出现了Dead Letter(死信),则按照这两个参数可以将消息重新路由到另一个Exchange(交换机),让消息重新被消费。
x-dead-letter-exchange:队列中出现Dead Letter后将Dead Letter重新路由转发到指定 exchange(交换机)。
x-dead-letter-routing-key:指定routing-key发送,一般为要指定转发的队列。
队列出现Dead Letter的情况有:
消息或者队列的TTL过期
队列达到最大长度
消息被消费端拒绝(basic.reject or basic.nack)

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;@Configuration
public class RabbitMQConfig {@Beanpublic Queue myQueue() {Map<String, Object> args = new HashMap<>();args.put("x-message-ttl", 3000); // 设置队列的过期时间为 3 秒args.put("x-dead-letter-exchange", "myExchange"); // 设置死信交换机args.put("x-dead-letter-routing-key", "myRoutingKey"); // 设置死信路由键return new Queue("myQueue", false, false, false, args);}@Beanpublic DirectExchange myExchange() {return new DirectExchange("myExchange");}@Beanpublic Binding binding(Queue myQueue, DirectExchange myExchange) {return BindingBuilder.bind(myQueue).to(myExchange).with("myRoutingKey");}
}

相关文章:

【延时队列的实现方式】

文章目录 延时队列JDK自带的延时队列实现Redis实现延迟队列RabbitMQ 延时队列 延时队列 延时队列是一种特殊类型的队列&#xff0c;它允许元素在特定时间间隔后才能被处理。这种队列在处理具有延迟需求的任务时非常有用&#xff0c;例如定时任务、事件驱动系统等 延时队列在项…...

Fyne ( go跨平台GUI )中文文档- 扩展Fyne (七)

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16 及更高版本, ide为goland2021.2 这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne ( go跨平台GUI…...

Qt (19)【Qt 线程安全 | 互斥锁QMutex QMutexLocker | 条件变量 | 信号量】

阅读导航 引言一、互斥锁1. QMutex&#xff08;1&#xff09;基本概念&#xff08;2&#xff09;使用示例基本需求⭕thread.h⭕thread.cpp⭕widget.h⭕widget.cpp 2. QMutexLocker&#xff08;1&#xff09;基本概念&#xff08;2&#xff09;使用示例 3. QReadWriteLocker、QR…...

Java语法-类和对象(上)

1. 面向对象的初步认识 1.1 什么是面向对象 概念: Java是一门纯面向对象的语言(Object Oriented Program&#xff0c;简称OOP)&#xff0c;在面向对象的世界里&#xff0c;一切皆为对象。 1.2 面向对象VS面向过程 如:洗衣服 面向过程: 注重的是洗衣服的过程,少了一个环节也不…...

Presto如何配置资源队列或资源组

Presto的任务队列配置主要涉及到查询队列和资源组的配置&#xff0c;这些配置通常用于管理Presto集群中的查询执行和资源分配。但是注意这两个东西是共存&#xff0c;互补的关系&#xff0c;并不需要纠结那种配置方式更加出色 一、查询队列配置 Presto的查询队列配置主要通过…...

828华为云征文|使用Flexus X实例集成ES搜索引擎

目录 一、应用场景 1.1 Flexus X实例概述 1.2 ES搜索引擎 二、安装相关服务 2.1 安装Elasticsearch7.17.0 2.2 安装kibana7.17.0 三、开通安全组规则 四、整体感受 4.1 Flexus X实例 4.2 使用感觉 一、应用场景 1.1 Flexus X实例概述 Flexus X实例是华为云推出的一款…...

【设计模式-访问者模式】

定义 访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为型设计模式&#xff0c;允许你在不修改已有类的情况下向这些类添加新的功能或行为。它通过将操作的执行逻辑从对象的类中分离出来&#xff0c;使得你可以在保持类的封闭性&#xff08;符合开闭原则&#xff…...

一元运算符(自增自减)

一、一元运算符 一元运算符&#xff0c;只需要一个操作数 1. 正号 正号不会对数字产生任何影响 2.-负号 负号可以对数字进行负号的取反 对于非Number的值&#xff0c;会将先转换为Number&#xff0c;在进行运算: 可以对一个其他的数据类型使用&#xff0c;来将其转换为n…...

gitlab/极狐-离线包下载地址

如果想要使用Gitlab/极狐进行数据的恢复&#xff0c;只能使用相同版本或者相近版本的安装包&#xff0c;因此有时候需要到它的官网上下载对应版本的安装包&#xff0c;以下是我收集到的对应地址的下载路径&#xff1a; Gitlab Gitlab离线库&#xff0c; https://packages.gitl…...

C++——输入三个整数,按照由小到大的顺序输出。用指针方法处理。

没注释的源代码 #include <iostream> using namespace std; void swap(int *m,int *n); int main() { int a,b,c; int *p1,*p2,*p3; cout<<"请输入三个整数&#xff1a;"<<endl; cin>>a>>b>>c; p1&a;p2&b;p3&c;…...

【Java8 重要特性】Lambda 表达式

文章目录 Lambda函数式接口Lambda 规则规范简化过程改写 Arrays.setAll()改写 Arrays.sort() forEach循环 list 集合循环 list 集合并输出对象信息循环 Map 集合 方法引用和构造器引用方法引用构造器引用 Lambda Lambda是一个匿名函数&#xff0c;我们可以将Lambda表达式理解为…...

word2vec--CBOW与Skip-Gram 两种模型

Word2Vec 是一种流行的用于生成词嵌入&#xff08;Word Embeddings&#xff09;的无监督学习模型&#xff0c;它由 Google 的一个团队在 2013 年提出。它的主要目的是将单词映射到一个连续的向量空间&#xff0c;使得语义相似的单词在这个空间中靠得更近。 Word2Vec 有两种主要…...

iOS六大设计原则设计模式

六大设计原则&#xff1a; 一、单一职责原则 一个类或者模块只负责完成一个职责或者功能。 类似于&#xff1a;UIView 和 CALayer 二、开放封闭原则 对扩展开放&#xff0c;对修改封闭。 我们要尽量通过扩展软件实体来解决需求变化&#xff0c;而不是通过修改已有的代码来…...

nacos 集群搭建

主机准备 IProle192.168.142.155slave02192.168.142.156slave192.168.142.157master 三台主机上分别构建 mysql 镜像 FROM mysql:8.0.31 ADD https://raw.githubusercontent.com/alibaba/nacos/develop/distribution/conf/mysql-schema.sql /docker-entrypoint-initdb.d/nac…...

STM32快速复习(十二)FLASH闪存的读写

文章目录 一、FLASH是什么&#xff1f;FLASH的结构&#xff1f;二、使用步骤1.标准库函数2.示例函数 总结 一、FLASH是什么&#xff1f;FLASH的结构&#xff1f; 1、FLASH简介 &#xff08;1&#xff09;STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分&…...

漏洞扫描工具使用

首先把补丁的两个文件复制下来替换原文件 找到C:\ProgramData\Acunetix\shared\license然后替换 然后打开漏扫工具并刷新页面 然后添加要扫描的网站 等他扫描完成 扫描完成就可以生成报告了 一共五十多页的报告...

C++ | Leetcode C++题解之第424题替换后的最长重复字符

题目&#xff1a; 题解&#xff1a; class Solution { public:int characterReplacement(string s, int k) {vector<int> num(26);int n s.length();int maxn 0;int left 0, right 0;while (right < n) {num[s[right] - A];maxn max(maxn, num[s[right] - A]);i…...

利士策分享,动摇时刻的自我救赎

利士策分享&#xff0c;动摇时刻的自我救赎 在人生的长河中&#xff0c;我们每个人都会面临各种挑战与抉择&#xff0c; 那些让人心生动摇的瞬间&#xff0c;如同夜空中偶尔掠过的乌云&#xff0c;遮蔽了前行的星光。 但正是这些动摇&#xff0c;构成了我们成长的轨迹&#x…...

动手学深度学习(李沐)PyTorch 第 1 章 引言

在线电子书 深度学习介绍 安装 使用conda环境 conda create -n d2l-zh python3.8 pip安装需要的包 pip install jupyter d2l torch torchvision下载代码并执行 wget https://zh-v2.d2l.ai/d2l-zh.zip unzip d2l-zh.zip jupyter notebookpip install rise如果不想使用jupyt…...

二叉树(二)深度遍历和广度遍历

一、层序遍历 广度优先搜索&#xff1a;使用队列&#xff0c;先进先出 模板&#xff1a; 1、定义返回的result和用于辅助的队列 2、队列初始化&#xff1a; root非空时进队 3、遍历整个队列&#xff1a;大循环while(!que.empty()) 记录每层的size以及装每层结果的变量&a…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...