在上一篇demo中,通过redis的zset加定时任务线程池实现了可持久化的延时任务。可实际情况比这个复杂的多,项目是分布式应用,延时任务的线程池单独一个项目,和其他项目互不干扰,这可怎么办?
添加其他的消息中间件吧,成本太高。那就用redis的发布订阅吧。总体的架构如下图所示:
线程池里面放的都是需要执行的延时任务。
下面看代码实现。
一、pom文件引入
org.springframework.boot
spring-boot-starter-data-redis
com.fasterxml.jackson.core
jackson-databind
两个必须的架包,一个是springboot整合redis的starter架包,一个是redis序列化的架包。需要注意的是,这里使用的SpringBoot版本是2.6.2,如果使用2.1.4.RELEASE版本,那么我们引入的架包会有所不同。这个可参考:SpringBoot整合Redis,订阅、发布、过期事件
二、启动类编码
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import com.example.demo.controller.DelayTaskExec;
/**
* 启动类
* @author 程就人生
* @Date
*/
@EnableScheduling
@SpringBootApplication
public class SrpingRedisMqDemoApplication implements CommandLineRunner{
// redis操作数据的模板类
@Autowired
private RedisTemplate redisTemplate;
// 延时任务线程池
@Autowired
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
// 日志打印
private static final Logger log = LoggerFactory.getLogger(SrpingRedisMqDemoApplication.class);
// 时间格式
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
SpringApplication.run(SrpingRedisMqDemoApplication.class, args);
}
// 处理缓存中遗留的延时任务
@Override
public void run(String... args) throws Exception {
ZSetOperations zset = redisTemplate.opsForZSet();
Long scheduleTime = System.currentTimeMillis();
Set