基于Redis实现分布式锁,避免重复执行定时任务

Spring提供了定时任务的功能,但是在多个实例的集群中,会出现定时任务重复执行多次的情况。

使用Qutaz框架自带的分布式定时任务可以很好的解决这个问题,但是讲道理功能有些过于强大,对于需求不高,乃至可以一定程度上允许失误的简单任务中,性价比比较低。

使用task任务时,可以通过在redis等缓存、数据库中创建锁来实现避免重复执行任务的功能。

基本思路如下:

  • 在redis中设置一个key作为锁,值为时间戳
  • 尝试用setnx方法直接设置锁,若成功则直接执行任务。
  • 若设置失败,使用getset方法获取当前锁并更新时间戳
  • 若获取的时间戳在有效期内,则不执行任务,否则执行任务

当然这种实现方法是很粗糙的。对于高并发的频繁定时任务处理很不完美。若执行失败也会导致任务丢失。

本方案实现的处理场景是间隔比较长的数据处理定时任务。服务器集群也只有三个节点,上线运行效果良好。

简要实现代码如下:

private boolean getLock(String key){
        String syncKey = "sync_lock_"+key;
        long curr = System.currentTimeMillis();
        String time = curr+"";
        long has = redisTemplate.setnx(syncKey,time);
        if(has == 1){
            return true;
        }else{
            String lock = redisTemplate.getSet(syncKey,time);
            if(lock == null){
                return true;
            }else{
                long l = NumberUtils.toLong(lock);
                //三十秒以内都算有效锁
                return Math.abs(curr-l)<30000;
            }
        }
    }
复制代码

你可能感兴趣的:(基于Redis实现分布式锁,避免重复执行定时任务)