1. 程式人生 > 實用技巧 >簡易的redis分散式鎖 RedisLockUtil

簡易的redis分散式鎖 RedisLockUtil

實現的訴求,多臺伺服器上,執行相同的方法,一次只能執行一個,如果多個請求了執行方法,那麼排隊等待執行。

方案:採用三方服務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));
            }
        }
    }