CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛

基于Springbootredis实现延时队列-永久免费的源码丞旭猿

◆ 什么是延迟队列?

首先,队列这种数据结构相信大家都不陌生,它是一种先进先出的数据结构。普通队列中的元素是有序的,先进入队列中的元素会被优先取出进行消费;

延时队列相比于普通队列最大的区别就体现在其延时的属性上,普通队列的元素是先进先出,按入队顺序进行处理,而延时队列中的元素在入队时会指定一个延迟时间,表示其希望能够在经过该指定时间后处理。从某种意义上来讲,延迟队列的结构并不像一个队列,而更像是一种以时间为权重的有序堆结构。

◆ 应用场景

下单成功后,X分钟内没有支付,自动取消订单

外卖场景,快要超时时给外卖小哥发送提醒通知

预定的会议开始前X分钟提醒

等等

◆ 方案

JDK中DelayQueue相关API

Quartz

Redis Zset(本文)

MQ

等等

◆ 实现

本文使用Redis Zset来实现延迟队列。

zset 是 Redis 提供的最具特色的数据类型之一,首先它是一个 set,这保证了内部 value 值的唯一性,其次它给每个 value 添加了一个 score(分值)属性,通过对分值的排序实现了有序化。比如用 zset 结构来存储学生的成绩,value 值代表学生的 ID,score 则是的考试成绩。我们可以对成绩按分数进行排序从而得到学生的的名次。

1、pom.xml

org.springframework.bootgroupId>spring-boot-starter-data-redisartifactId>dependency>

application.yml

spring:redis:host: localhostport: 6379password: xxxdatabase: 1

2、延迟任务对象定义

public interface RedisDelayTask {/*** 任务ID* @return*/String getId();

/*** 队列中的值* @return*/String getValue();

/*** 延迟时间(单位:s)* @return*/long getDelayTime();

/*** 任务执行*/void execute();}

/*** 抽象任务*/public abstract class AbstractRedisDelayTask implements RedisDelayTask {

protected String id;protected String value;private long delayTime;

public AbstractRedisDelayTask(String id, String value, long delayTime) {this.id = id;this.value = value;this.delayTime = delayTime;}

@Overridepublic String getId() {return id;}

public void setId(String id) {this.id = id;}

@Overridepublic String getValue() {return value;}

public void setValue(String value) {this.value = value;}

@Overridepublic long getDelayTime() {return delayTime;}

public void setDelayTime(long delayTime) {this.delayTime = delayTime;}

@Overridepublic String toString() {return "RedisDelayTask{" +"id=" + id + \ +", value=" + value + \ +", delayTime=" + delayTime +};}}

3、通知类任务定义

public class NoticeTask extends AbstractRedisDelayTask {

private final static Logger LOGGER = LoggerFactory.getLogger(NoticeTask.class);

public NoticeTask(String id, String value, long delayTime) {super(id, value, delayTime);}

@Overridepublic void execute() {LOGGER.info("task execute, {}", this);}}

4、任务管理

@Componentpublic class RedisDelayQueueManager implements InitializingBean {

@Autowiredprivate StringRedisTemplate redisTemplate;/*** 任务列表*/private Map tasks = new ConcurrentHashMap<>();

/*** 添加延迟任务到队列* @param task*/public void addTask(RedisDelayTask task) {long delayedTime = System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(task.getDelayTime(), TimeUnit.SECONDS);boolean r = redisTemplate.opsForZSet().add(task.getId(), task.getValue(), delayedTime);if (r) {tasks.put(task.getId(), task);}}

/*** 检查并执行任务*/private void checkAndExecuteTask() {while ( true) {Set taskIds = tasks.keySet();for (String taskId : taskIds) {// score就是任务要执行的时间点,如果<=当前时间,说明任务该执行了Set > tuples = redisTemplate.opsForZSet().rangeByScoreWithScores(taskId, 0, System.currentTimeMillis());if (!CollectionUtils.isEmpty(tuples)) {for (ZSetOperations.TypedTuple tuple : tuples) {// 移除并执行任务RedisDelayTask task = tasks.remove(taskId);if (task != null) {task.execute();// 从队列中删除redisTemplate.opsForZSet().remove(taskId, tuple.getValue());}}}}}}

@Overridepublic void afterPropertiesSet() throws Exception {// 新起一个线程执行任务new Thread(() -> {checkAndExecuteTask();}, "redis-delay-task").start();}}

5、测试

@RunWith(SpringRunner.class)@SpringBootTest(classes = RedisApplication.class)public class RedisDelayTaskTest {@Autowiredprivate RedisDelayQueueManager redisDelayQueueManager;

@Testpublic void addTask() throws IOException {NoticeTask task = new NoticeTask("notice-task", "notice-task-value", 5);redisDelayQueueManager.addTask(task);NoticeTask task2 = new NoticeTask("notice-task2", "notice-task-value2", 10);redisDelayQueueManager.addTask(task2);System.in.read();}}

执行结果如下:

2022-01-22 17:27:53.428 INFO 86506 — [ main] io.lettuce.core.KqueueProvider : Starting without optional kqueue library 2022-01-22 17:27:58.140 INFO 86506 — [edis-delay-task] c.springboot.demo.redis.task.NoticeTask : task execute, RedisDelayTask{id=notice-task, value=notice-task-value, delayTime=5} 2022-01-22 17:28:03.925 INFO 86506 — [edis-delay-task] c.springboot.demo.redis.task.NoticeTask : task execute, RedisDelayTask{id=notice-task2, value=notice-task-value2, delayTime=10}

免责声明:

本公众号部分分享的资料来自网络收集和整理,所有文字和图片版权归属于原作者所有,且仅代表作者个人观点,文章仅供读者学习交流使用,并请自行核实相关内容,如文章内容涉及侵权,请联系后台管理员删除。

声明:本文部分素材转载自互联网,如有侵权立即删除 。

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
相关推荐
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容