Java基于redis的延迟任务,适用于微服务、集群项目

本文详细介绍了如何在Java微服务和集群项目中利用Redis实现延迟任务。内容包括生产者(producer)的设计,计时器的实现,消费者(consumer)的逻辑,以及测试延迟执行器的步骤。在微服务环境中,生产者发送或取消延迟任务,通过ScheduledThreadPoolExecutor进行定时触发。消费者通过Redis中的值获取并执行任务。虽然依赖于Redis,但提供了持久化和解耦的优势,同时也指出了可能存在的问题及优化方案。
摘要由CSDN通过智能技术生成

一、原理流程图

 二、原理解析

2.1 producer(生产者)

1.生产者为延迟执行器的客户端,发送或取消延迟任务;

2.在spring容器中注入DelayTaskProducer bean,初始化需要3个参数ApplicationContext、redis工具类、自定义任务key(注意:key在不同微服务中一定不能重复);

3.初始化完成,即可注入使用;

话外:如果是单个服务,ApplicationContext和自定义任务key,这两个参数就没有必要了,可以直接利用映射初始化用户的实现类,但是,该功能也就和项目不能解耦了;

package com.geo.source.redis.delaytask_v2;

import com.alibaba.fastjson.JSONObject;
import com.geo.source.redis.delaytask_v2.timer.DelayTaskConstant;
import com.geo.source.redis.delaytask_v2.timer.DelayTaskDto;
import com.geo.source.redis.delaytask_v2.timer.DelayTaskTimer;
import org.springframework.context.ApplicationContext;
import redis.clients.jedis.JedisCluster;

import java.time.LocalDateTime;
import java.time.ZoneOffset;

/**
 * 延迟任务-生产者
 * <pre>
 * 消费任务:实现DelayTaskConsumer接口,并注入spring容器中(例:使用@Service);
 * 如何生产任务:通过注入该类,使用producer方法生产延迟任务
 * </pre>
 *
 * @author YanZhen
 * @date 2020/04/16 00:19
 **/
public class DelayTaskProducer {

    /**
     * redis初始化
     */
    private JedisCluster redis;
    /**
     * redis key 不同中心指定不同的key值
     */
    private String redisKey;

    /**
     * 定时器对象
     */
    private DelayTaskTimer timer;

    /**
     * 不允许无参初始化
     */
    private DelayTaskProducer() {
    }

    /**
     * 延迟任务生产者
     *
     * @param context  spring上下文,用户获取用户实现的消费者
     * @param redis    redis 初始化
     * @param redisKey 不同中心指定不同的key值,否则会不消费
     */
    public DelayTaskProducer(ApplicationContext context, JedisCluster redis, String redisKey) {
        if (redisKey == null || redisKey.isEmpty()) {
            throw new IllegalArgumentException("初始化延迟任务生产者,redis key必须输入!");
        }

        redisKey = DelayTaskConstant.REDIS_KEY + redisKey;
        this.redis = redis;
        this.redisKey = redisKey;
        // 延迟任务计时器启动
        this.timer = new DelayTaskTimer(context, redis, redisKey);
    }

    /**
     * 生产任务
     * 注意:通过是实现DelayTaskConsumer接口,进行消费
     *
     * @param clazz  自定义的消费者类实现类
     * @param params 传参
     * @param time   任务延迟消费的时间(单位:秒)
     * @return 是否生产
     */
    public boolean producer(Class<? extends DelayTaskConsumer> clazz, String params, long time) {
        // 添加消息队列
        final Long aLong = redis.zadd(redisKey, LocalDateTime.now().plusSeconds(time).toEpochSecond(ZoneOffset.of("+8")),
                JSONObject.toJSONString(new DelayTaskDto(clazz, params)));

        boolean b = aLong != null && aLong > 0;
        if (b) {
            // 解除定时器的睡眠
            timer.notifyAll1();
        }
        return b;
    }

    /**
     * 取消延迟任务
     * @param clazz 自定义的消费者实现类
     * @param params 传参;注意:一定要和生成任务时传递的参数相同,否则无法定位redis里的任务
     * @return 是否成功
     */
    public
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值