延迟队列的实际使用案例

首先我们需要一个延迟队列provider,这个需要注入一个redisson客户端

@Component
public class DelayedQueueProvider {

    private final RedissonClient redissonClient;

    // 配置已经自动注入构造完成
    public DelayedQueueProvider(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    /**
     * 添加延迟任务
     *
     * @param delayedName 延迟名称
     * @param val         值
     * @param delayTime   延迟时间
     * @param timeUnit    时间单位
     * @param env 环境信息
     */
    public void addDelayedTask(String delayedName, String val, long delayTime, TimeUnit timeUnit, String env) {
        final DelayedTaskInfo task = new DelayedTaskInfo();
        task.setCreateAt(System.currentTimeMillis());
        task.setDelayTime(delayTime);
        task.setTimeUnit(timeUnit);
        task.setVal(val);
        task.setDelayedName(env + "-" + delayedName);
        final RDelayedQueue<DelayedTaskInfo> delayedQueue = getDelayedQueue(env + "-" + delayedName);
        delayedQueue.offer(task, delayTime, timeUnit);
    }

    /**
     * 获取阻塞deque
     *
     * @param queueName 队列名称
     * @return {@link RBlockingDeque}<{@link DelayedTaskInfo}>
     */
    public RBlockingDeque<DelayedTaskInfo> getBlockingDeque(String queueName) {
        return redissonClient.getBlockingDeque(queueName, JsonJacksonCodec.INSTANCE);
    }

    /**
     * 获取延迟队列
     *
     * @param queueName 队列名称
     * @return {@link RDelayedQueue}<{@link DelayedTaskInfo}>
     */
    private RDelayedQueue<DelayedTaskInfo> getDelayedQueue(String queueName) {
        return redissonClient.getDelayedQueue(getBlockingDeque(queueName));
    }


}

再写一个任务启动Listener

@RequiredArgsConstructor
@Slf4j
@Component
public class DelayedTaskListener implements ApplicationRunner {

    private final DelayedQueueProvider delayedQueueProvider;

    @Value("${spring.profiles.active}")
    private String env;

    @Autowired
    private BusinessService businessService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        delayedTaskHandle(env + "-" + QueueConstant.SWITCH_CONTROL_DELAYED_TASK_QUEUE);
    }

    public void delayedTaskHandle(String delayedQueueName) {
        final Thread thread = new Thread(() -> {
            final RBlockingDeque<DelayedTaskInfo> blockingDeque = delayedQueueProvider.getBlockingDeque(delayedQueueName);
            while (true) {
                try {
                    //将到期的数据取出来,等待超时0.5s
                    final DelayedTaskInfo delayedTaskInfo = blockingDeque.poll(500, TimeUnit.MILLISECONDS);
                    if (Objects.isNull(delayedTaskInfo)) {
                        continue;
                    }
                    log.info("DelayedTask task :[{}]", delayedTaskInfo);
                    // 这里可以替换成为你们自己的业务,就是把存进去的json转为对象,然后在进行业务处理
                    //SyncSwitchControlReq req = JsonTool.jsonToObject(delayedTaskInfo.getVal(), SyncSwitchControlReq.class);
                    //businessService.syncSwitchControl(req);
                } catch (Exception e) {
                    log.error("DelayedTaskListener#delayedTaskHandle error delayedQueueName:[{}]", delayedQueueName, e);
                }
            }
        });
        // 设置成为守护线程
        thread.setDaemon(true);
        thread.start();
    }
}

在实际的业务的位置进行使用:需要注入该provider,调用方法addDelayedTask(),我这里的req是我要往队列里放的数据,我是直接存储为json,比较方便

// 往队列里添加任务
delayedQueueProvider.addDelayedTask(
        QueueConstant.SWITCH_CONTROL_DELAYED_TASK_QUEUE,
        JsonTool.dataToJson(req),
        500,
        TimeUnit.MILLISECONDS,
        env
);
posted @ 2025-01-27 15:38  程序员鲜豪  阅读(5)  评论(0编辑  收藏  举报