关于定时任务轮询的解决方法

有几个场景业务的处理:

一:有一个很大的商品订单表,每天新增数十万条数据。每条数据有个到期时间,需要在到期时间后做一些处理,譬如关闭订单,改变状态之类的。

二:有个付款功能,有到期时间,时间到了需要关闭,或者通知用户等等。

三:抢购时,时间到了,用户不处理不付款的,要把商品回到库存里之类的。 大概类似的一些有到期时间功能的业务场景,但是要么是有较强的实时性,譬如希望到期后立马就改变状态或者做出一些通知之类的,要么是数据量巨大的。 那么可能首先想到的思路就是开个定时任务,隔一段时间去扫一下表,看看到期时间,然后做处理。 很明显,扫表是个很大的工作量,耗时耗资源,甚至会产生死锁什么的。而且大部分时候的扫描是无用的,产生了很多无用的查询。

那么这种问题解决思路: 在添加数据时,将ID和过期时间放到redis里,用那个能排序的结构sortSet,或者类似的能记录时间的中间件,做好排序。然后起个后台任务或者新起个项目,专门是扫描这个redis的第一条数据,也就是最快要过期的,这样只需要查询一条就行了,只要第一条不过期,那后面的就不用看了,也就不需要去操作数据库。倘若第一条过期了,就做相应的处理,然后移除掉,再去扫第二条,依次类推。这样查询就很少,也不需要查表。所以可以把扫描间隔设的很短,来达到强实时性。

这个就是解决的思路

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class ExpirationTaskProcessor {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    // 添加任务到Redis
    public void addTask(String taskId, long expireTime) {
        redisTemplate.opsForZSet().add("expiration_tasks", taskId, expireTime);
    }

 

@Scheduled(fixedDelay = 1000)
public void processExpirationTasks() {
    long now = System.currentTimeMillis();

    while (true) {
        // 获取第一条即将过期的任务
        Set<Object> tasks = redisTemplate.opsForZSet().rangeByScore("expiration_tasks", 0, now, 0, 1);

        // 如果没有过期任务,退出循环
        if (tasks == null || tasks.isEmpty()) {
            break;
        }

        Object taskId = tasks.iterator().next();

        // 执行过期处理逻辑
        processExpiredTask(taskId);

        // 从Redis中移除已处理的任务
        redisTemplate.opsForZSet().remove("expiration_tasks", taskId);
    }
}

    private void processExpiredTask(Object taskId) {
        // 在这里实现过期任务的处理逻辑
        System.out.println("Processing expired task: " + taskId);
        // 例如:关闭订单、通知用户等
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值