Spring Boot集成Redisson实现延迟队列

项目场景:

   在电商、支付等领域,往往会有这样的场景,用户下单后放弃支付了,那这笔订单会在指定的时间段后进行关闭操作,细心的你一定发现了像某宝、某东都有这样的逻辑,而且时间很准确,误差在1s内;那他们是怎么实现的呢?

   一般实现的方法有几种:使用 redisson、rocketmq、rabbitmq等消息队列的延时投递功能。


解决方案:

   一般项目集成redis的比较多,所以我这篇文章就说下redisson延迟队列,如果使用rocketmq或rabbitmq需要额外集成中间件,比较麻烦一点。

1.集成redisson

maven依赖

<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.21.1</version>
</dependency>

yml配置,单节点配置可以兼容redis的配置方式

# redis配置
spring:redis:database: 0host: 127.0.0.1password: redis@passport: 6001

 更详细的配置参考:Spring Boot整合Redisson的两种方式-CSDN博客

2.配置多线程

因为延迟队列可能会多个任务同时执行,所以需要多线程处理。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;@Configuration
@EnableAsync
public class ExecutorConfig {/*** 异步任务自定义线程池*/@Bean(name = "taskExecutor")public ThreadPoolTaskExecutor asyncServiceExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//配置核心线程数executor.setCorePoolSize(50);//配置最大线程数executor.setMaxPoolSize(500);//配置队列大小executor.setQueueCapacity(300);//允许线程空闲时间executor.setKeepAliveSeconds(60);//配置线程池中的线程的名称前缀executor.setThreadNamePrefix("taskExecutor-");// rejection-policy:当pool已经达到max size的时候,如何处理新任务// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//调用shutdown()方法时等待所有的任务完成后再关闭executor.setWaitForTasksToCompleteOnShutdown(true);//等待所有任务完成后的最大等待时间executor.setAwaitTerminationSeconds(60);return executor;}
}

3.具体业务

比如消息通知、关闭订单等 ,这里加上了@Async注解,可以异步执行

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;import java.text.SimpleDateFormat;
import java.util.Date;@Service
public class AsyncService {@Asyncpublic void executeQueue(Object value) {System.out.println();System.out.println("当前线程:"+Thread.currentThread().getName());System.out.println("执行任务:"+value);//打印时间方便查看SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("执行任务的时间:"+sdf.format(new Date()));//自己的业务逻辑,可以根据id发送通知消息等//......}
}

4.延迟队列(关键代码)

这里包括添加延迟队列,和消费延迟队列,@PostConstruct注解的意思是服务启动加载一次,参考

Spring Boot项目启动时执行指定的方法-CSDN博客Spring Boot中多个PostConstruct注解执行顺序控制_多个postconstruct执行顺序-CSDN博客

import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;@Service
public class TestService {@Resourceprivate AsyncService asyncService;@Resourceprivate ThreadPoolTaskExecutor executor;@Autowiredprivate RedissonClient redissonClient;/*** 添加延迟任务*/public void addQueue() {//获取延迟队列RBlockingQueue<Object> blockingQueue = redissonClient.getBlockingQueue("delayedQueue");RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingQueue);for (int i = 1; i <= 10; i++) {long delayTime = 5+i; //延迟时间(秒)
//			long delayTime = 5; //这里时间统一,可以测试并发执行delayedQueue.offer("延迟任务"+i, delayTime, TimeUnit.SECONDS);}//打印时间方便查看SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("添加任务的时间:"+sdf.format(new Date()));}/***	服务启动时加载,开始消费延迟队列*/@PostConstructpublic void consumer() {System.out.println("服务启动时加载>>>>>>");//获取延迟队列RBlockingQueue<Object> delayedQueue = redissonClient.getBlockingQueue("delayedQueue");//启用一个线程来消费这个延迟队列executor.execute(() ->{while (true){try {
//					System.out.println("while中的线程:"+Thread.currentThread().getName());//获取延迟队列中的任务Object value = delayedQueue.poll();if(value == null){//如果没有任务就休眠1秒,休眠时间根据业务自己定义Thread.sleep(1000);	//这里休眠时间越短,误差就越小continue;}//异步处理延迟队列中的消息asyncService.executeQueue(value);} catch (Exception e) {e.printStackTrace();}}});}
}

5.测试接口 

import com.test.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/test")
public class TestController {@Autowiredprivate TestService testService;/** 添加延迟任务*/@GetMapping(value = "/addQueue")public String addQueue() {testService.addQueue();return "success";}}

6.测试结果


 总结:

  1. Redisson的的RDelayedQueue是基于Redis实现的,而Redis本身并不保证数据的持久性。如果Redis服务器宕机,那么所有在RDelayedQueue中的数据都会丢失。因此,我们需要在应用层面进行持久化设计,例如定期将RDelayedQueue中的数据持久化到数据库。
  2. 在设计延迟任务时,我们应该根据实际需求来合理设置延迟时间,避免设置过长的延迟时间导致内存占用过高。

源码:https://download.csdn.net/download/u011974797/89225515 

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

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

相关文章

与AI对话:探索最佳国内可用的ChatGPT网站

与AI对话&#xff1a;探索最佳国内可用的ChatGPT网站 &#x1f310; 链接&#xff1a; GPTGod 点击可注册 &#x1f3f7;️ 标签&#xff1a; GPT-4 支持API 支持绘图 Claude &#x1f4dd; 简介&#xff1a;GPTGod 是一个功能全面的平台&#xff0c;提供GPT-4的强大功能&…

JavaEE——Spring Boot + jwt

目录 什么是Spring Boot jwt&#xff1f; 如何实现Spring Boot jwt&#xff1a; 1. 添加依赖 2、创建JWT工具类 3. 定义认证逻辑 4. 添加过滤器 5、 http请求测试 什么是Spring Boot jwt&#xff1f; Spring Boot和JWT&#xff08;JSON Web Token&#xff09;是一对常…

苍穹外卖学习

并不包含全部视频内容&#xff0c;大部分都按照操作文档来手搓代码&#xff0c;资料&#xff0c;代码都上传git。 〇、实际代码 0.1 Result封装 package com.sky.result;import lombok.Data;import java.io.Serializable;/*** 后端统一返回结果* param <T>*/ Data pub…

启动MySQL服务

在 Windows 系统上&#xff1a; 首先&#xff0c;找到 MySQL 安装目录&#xff0c;一般默认是在 C:\Program Files\MySQL 文件夹下。进入该目录下的 bin 文件夹。找到 mysqld.exe 文件&#xff0c;双击运行它。 在 Linux 系统&#xff08;以 CentOS 为例&#xff09;&#xff…

软考 系统架构设计师系列知识点之软件可靠性基础知识(5)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之软件可靠性基础知识&#xff08;4&#xff09; 所属章节&#xff1a; 第9章. 软件可靠性基础知识 第1节 软件可靠性基本概念 9.1.3 可靠性目标 前文定量分析软件的可靠性时&#xff0c;使用失效强度来表示软件缺陷对…

20232937文兆宇 2023-2024-2 《网络攻防实践》实践七报告

20232937文兆宇 2023-2024-2 《网络攻防实践》实践七报告 1.实践内容 &#xff08;1&#xff09;使用Metasploit进行Linux远程渗透攻击 任务&#xff1a;使用Metasploit渗透测试软件&#xff0c;攻击Linux靶机上的Samba服务Usermap_script安全漏洞&#xff0c;获取目标Linux…

mysql 意向锁

文章目录 问题锁作用防止死锁提高并发性能问题 先看问题 事务A select * from table where id=1 for update会把id=1这一行锁住 事务B lock table in share mode这时B 想加表级别的共享锁,如果这时想加表级别的共享锁,那就要去挨个检查每行是不是有排它锁 ,这时如果在…

机器学习day3

一、距离度量 1.欧氏距离 2.曼哈顿距离 3.切比雪夫距离 4.闵可夫斯基距离 二、特征与处理 1.数据归一化 数据归一化是一种将数据按比例缩放&#xff0c;使之落入一个小的特定区间的过程。 代码实战 运行结果 2.数据标准化 数据标准化是将数据按照其均值和标准差进行缩放的过…

2024新版计算机网络视频教程65集完整版(视频+配套资料)

今日学计算机网络&#xff0c;众生皆叹难理解。 却见老师神乎其技&#xff0c;网络通畅如云烟。 协议层次纷繁复杂&#xff0c;ARP、IP、TCP、UDP。 路由器交换机相连&#xff0c;数据包穿梭无限。 网络安全重于泰山&#xff0c;防火墙、加密都来添。 恶意攻击时刻存在&#xf…

VUE3与Uniapp 三 (属性绑定)

<template><image :src"pic"></image><!-- 此时loading的false是字符串&#xff0c;不是布尔类型 --><button loading"false">按钮1</button><!-- 此时loading使用了属性绑定&#xff0c;这时的false是布尔类型 --…

python小知识:@property、@setter 使用

在 Python 中&#xff0c;property 是一种装饰器&#xff0c;可以将一个方法转换为属性&#xff0c;使其可以像访问属性一样被调用&#xff0c;而不是像调用方法一样。 使用 property 装饰器可以将一个方法转换为只读属性&#xff0c;也可以通过定义 setter 方法来实现可写属性…

Visual Studio Code使用

目录 1.python的调试 2.c的运行 方法1&#xff1a; 方法2&#xff1a; 3.c的调试 3.1调试方法一&#xff1a;先生成执行文件&#xff0c;再调试 3.2调试方法二&#xff1a;同时生成执行文件&#xff0c;调试 4.tasks.json 与launch.json文件的参考 4.1C生成执行文件tas…

AI视频教程下载:用ChatGPT和 MERN 堆栈构建 SAAS 项目

这是一个关于 掌握ChatGPT 开发应用的全面课程&#xff0c;它将带领你进入 AI 驱动的 SAAS 项目的沉浸式世界。该课程旨在使你具备使用动态的 MERN 堆栈和无缝的 Stripe 集成来构建强大的 SAAS 平台所需的技能。 你将探索打造智能解决方案的艺术&#xff0c;深入研究 ChatGPT 的…

【QT进阶】Qt线程与并发之QtConcurrent返回值与run方法的参数说明

往期回顾 【QT进阶】Qt线程与并发之线程和并发的简单介绍-CSDN博客 【QT进阶】Qt线程与并发之创建线程的三种方法(超详细介绍)-CSDN博客 【QT进阶】Qt线程与并发之QtConcurrent的简单介绍-CSDN博客 【QT进阶】Qt线程与并发之QtConcurrent返回值与run方法的参数说明 一、QtConc…

FMU精度问题

1.fmu存在的本质意义是连接来自不同学科的模型&#xff0c;进行多学科协同仿真&#xff0c;提高工作效率并降低开发成本&#xff0c;而不是对求解精度的复现&#xff1b; 2.建模工具的开发语言不确定&#xff0c;但是生成fmu的语言皆为C语言&#xff0c;所以每种开发语言、每款…

使用R语言进行简单的主成分分析(PCA)

主成分分析&#xff08;PCA&#xff09;是一种广泛使用的数据降维技术&#xff0c;它可以帮助我们识别数据中最重要的特征并简化复杂度&#xff0c;同时尽量保留原始数据的关键信息。在这篇文章中&#xff0c;我们将通过一个具体的例子&#xff0c;使用R语言实现PCA&#xff0c…

主成分分析(PCA):揭秘数据的隐藏结构

在数据分析的世界里&#xff0c;我们经常面临着处理高维数据的挑战。随着维度的增加&#xff0c;数据处理、可视化以及解释的难度也随之增加&#xff0c;这就是所谓的“维度的诅咒”。主成分分析&#xff08;PCA&#xff09;是一种强大的统计工具&#xff0c;用于减少数据的维度…

深度学习模型训练优化:并行化策略与参数拆分技术

目录 并行处理 1. 张量并行(Tensor Parallelism) 工作原理 优点 缺点

Maven的仓库、周期和插件

一、简介 随着各公司的Java项目入库方式由老的Ant改为Maven后&#xff0c;相信大家对Maven已经有了个基本的熟悉。但是在实际的使用、入库过程中&#xff0c;笔者发现挺多人对Maven的一些基本知识还缺乏了解&#xff0c;因此在此处跟大家简单地聊下Maven的相关内容&#xff0c…

二 SpringMVC接收数据

SpringMVC接收数据 一 访问路径以及指定请求方法 Controller public class UserController {/*** WebSevlet (" 必须以/开头")* RequstMapping(" 不要求 / 开头 ")*1. 精准地址 &#xff0c;多个 ("地址1“&#xff0c;”地址2“)* 2. 支持模糊查询…