集群下利用redis实现分布式锁来保证只有一个服务器执行定时任务

利用redis的setnx定时分布式锁,核心代码如下:

/**
  * 给key上锁,锁的时间长为seconds秒
  * 
  * @param key
  * @param seconds
  * @return
  */
 public static boolean setLock(String key, int seconds) {
  Jedis client = getJedis();
  if (client == null) {
   return false;
  }
  try {
   Long lock = client.setnx(key, "1");
   if (lock > 0) {
    client.expire(key, seconds);
    return true;
   }
  } catch (Exception e) {
   return false;
  } finally {
   if (null != client) {
    client.close();
   }
  }
  return false;
 }

下面这个为分布式锁工具类

/**
 * @author hyd
 *
 */
public class RedisDistributedLock {
	//定时补充redisKey过期时间的代码。如果不手动清除这个key或关闭定任务,则会一直进入锁定状态。
       public static final Map<String, Timer> timerMap = new Hashtable<>();
       //锁前缀
       private static final String REDIS_LOCK = "project:distribued:lock:";
       // 锁key默认过期时间,单位为分钟
 	private static final int lockTime = 3 * 60;
	
	
}

整体复制代码,好像会出错,我把方法分开写入,您把以下代码复制到工具类中就可以了。

上锁

public static boolean lock(String key, int lockTime) {
	String lockKey = REDIS_LOCK + key;
  // redisCache是redispool封装的单例
  boolean lock = setLock(lockKey, lockTime);
  if (lock) {
   redisLock(key, lockTime);
   return lock;
  }
  return lock;
}

重载上锁


public static boolean lock(String key){
	return lock(key, lockTime);
}

解锁


public static void  releaseLock(String key) {
String lockKey = REDIS_LOCK + key;
RedisCache.getInstance().del(lockKey);
Timer timer = timerMap.get(key);
  if (timer != null) {
   timer.cancel();
   }

}

定时补充key时间

public static void redisLock(String key, int lockTime){
String lockKey = REDIS_LOCK + key;
//线程池运行
ThreadPoolUtil.execute(new Runnable() {
@Override
   public void run() {
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
@Override
     public void run() {
      if (timerMap.get(key) != null) {
       RedisCache.getInstance().expireLock(lockKey, lockTime);
      }
     }
    }, 10, lockTime * 1000 / 3);
    timerMap.put(key, timer);
});
}
}

用法,利用main方法测试如下:

public static void main(String[] args) {
// 不指定时间,默认为3分钟。执行完成后,释放锁。
  String key = "reportTimer";
  boolean lock = RedisDistributedLock.lock(key);
  try {
   if (lock) {
    timerTask();
   }
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   RedisDistributedLock.releaseLock(key);
  }

// 不指定时间,默认为3分钟。执行完成后,不释放锁。
  String key1 = "reportTimer1";
  boolean lock1 = RedisDistributedLock.lock(key1);
  try {
   if (lock1) {
    timerTask();
   }
  } catch (Exception e) {
   e.printStackTrace();
  }


// 指定时间,为5分钟。执行完成后,释放锁。
  String key2 = "reportTimer2";
  boolean lock2 = RedisDistributedLock.lock(key2, 5 * 60);
  try {
   if (lock2) {
    timerTask();
   }
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   RedisDistributedLock.releaseLock(key2);
  }

// 指定时间,为5分钟。执行完成后,不释放锁。
  String key3 = "reportTimer3";
  boolean lock3 = RedisDistributedLock.lock(key3, 5 * 60);
  try {
   if (lock3) {
    timerTask();
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
}
private static void timerTask() {
  System.out.println("此处为定时任务的逻辑!编写代码时,此处可以删除");
 }

以上工具类,适用于项目集群定时任务的执行。具体有什么不懂的,可以私信我。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值