簡易的redis分散式鎖 RedisLockUtil
阿新 • • 發佈:2021-01-20
實現的訴求,多臺伺服器上,執行相同的方法,一次只能執行一個,如果多個請求了執行方法,那麼排隊等待執行。
方案:採用三方服務redis的key做唯一標識控制。超時後。
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.util.StringUtils; import com.ccjr.commons.utils.SpringUtils; import lombok.extern.slf4j.Slf4j; /** * @desc REDIS分散式鎖工具類 * @author 陳惟鮮 chenweixian * @date 2020年8月19日 下午4:20:46 **/ @Slf4j public class RedisLockUtil { @SuppressWarnings("unchecked") private static RedisTemplate<String, Object> redisTemplate = (RedisTemplate<String, Object>) SpringUtils.getBean("redisTemplate"); private static long lockTimeout = 5*1000L; //鎖定時間30s /** * 加鎖 * * @param key * @param value 當前時間+ 超時時間 * @return*/ public static boolean lock(String key, long currvalue) { String value = currvalue+lockTimeout+""; //未加鎖,則加鎖 if (redisTemplate.opsForValue().setIfAbsent(key, value)) { return true; } do { //獲取鎖解鎖時間 String currentValue = (String)redisTemplate.opsForValue().get(key); //如果鎖過期 if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) { //獲得上一個鎖的時間 String olcValue = (String)redisTemplate.opsForValue().getAndSet(key, value); if (!StringUtils.isEmpty(olcValue) && olcValue.equals(currentValue)) { return true; } } try { // log.info("等待500 ms key:{},value:{},cur:{}, 剩餘:{}",key,value, System.currentTimeMillis(), Long.parseLong(value)-System.currentTimeMillis()); Thread.sleep(500); } catch (InterruptedException e) { } }while(Long.parseLong(value) > System.currentTimeMillis()); return false; } /** * 解鎖 * * @param key * @param value */ public static void unlock(String key, long currvalue) { try { String value = currvalue+lockTimeout+""; String currentVlue = (String)redisTemplate.opsForValue().get(key); if (!StringUtils.isEmpty(currentVlue) && currentVlue.equals(value)) { redisTemplate.opsForValue().getOperations().delete(key); } } catch (Exception e) { log.error("【redis分散式鎖】 解鎖異常" + e.getMessage(), e); } } }
測試:
@Test public void testRedisLock() { String key = "testRedisLock"; for (int i=0;i<100;i++) { long currvalue = System.currentTimeMillis(); try { System.out.println(i + "A="+ RedisLockUtil.lock(key, currvalue)); System.out.println("做了些事情開始。。"); // try { // Thread.sleep(4000); // } catch (InterruptedException e) {} System.out.println("做了些事情結束。。"); } finally { currvalue = System.currentTimeMillis(); System.out.println(i + "B="+ RedisLockUtil.lock(key, currvalue)); RedisLockUtil.unlock(key, currvalue); System.out.println(i + "C="+ RedisLockUtil.lock(key, currvalue)); } } }