クラスタの下でredisを使用して分散ロックを実現し、1つのサーバだけがタイミングタスクを実行することを保証します.

21453 ワード

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();
   }

}


タイミング補充キー時間
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("          !     ,      ");
 }

以上のツールクラスは、プロジェクトクラスタのタイミングタスクの実行に適しています.具体的に何か分からないことがあったら、私を信用してください.