1 源碼
package com.yx.redis.jedis; import lombok.extern.slf4j.Slf4j; import java.util.Collections; /** * @Auther: yx * @Date: 2019-05-05 16:13 * @Description: DistributedLocker */ @Slf4j public class JedisDistributedLocker { private static final String LOCK_SUCCESS = "OK"; private static final Long RELEASE_SUCCESS = 1L; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX"; private static final String UNLOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; private static final int RETRY_TIME = 100; private JedisTemplate jedisTemplate; public JedisDistributedLocker(JedisTemplate jedisTemplate) { this.jedisTemplate = jedisTemplate; } /** * 嘗試獲取分布式鎖 * @param lockKey 鎖 * @param requestId 請求標識 * @param expireTime 超期時間 * @return 是否獲取成功 */ public boolean lock(String lockKey, String requestId, int expireTime) { String result = jedisTemplate.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); if (LOCK_SUCCESS.equals(result)) { return true; } return false; } /** * 加鎖 * @param lockKey * @param waitTime 等待時間 * @param expireTime 強制鎖釋放時間 * @return */ public boolean tryLock(String lockKey, String requestId, int waitTime, int expireTime) { int alreadyWaitTime = 0; while (waitTime > alreadyWaitTime) { if (lock(lockKey, requestId, expireTime)) { return true; } else { try { Thread.sleep(RETRY_TIME); } catch (InterruptedException e) { log.warn(e.getMessage(), e); return false; } } alreadyWaitTime += RETRY_TIME; } return false; } /** * 釋放分布式鎖 * @param lockKey 鎖 * @param requestId 請求標識 * @return 是否釋放成功 */ public boolean unlock(String lockKey, String requestId) { Object result = jedisTemplate.eval(UNLOCK_SCRIPT, Collections.singletonList(lockKey), Collections.singletonList(requestId)); if (RELEASE_SUCCESS.equals(result)) { return true; } return false; } }
2 加鎖命令說明
SET key value [EX seconds] [PX milliseconds] [NX|XX]
將字符串值 value 關聯到 key 。
如果 key 已經持有其他值, SET 就覆寫舊值,無視類型。
對於某個原本帶有生存時間(TTL)的鍵來說, 當 SET 命令成功在這個鍵上執行時, 這個鍵原有的 TTL 將被清除。
可選參數
從 Redis 2.6.12 版本開始, SET 命令的行為可以通過一系列參數來修改:
-
- EX second :設置鍵的過期時間為 second 秒。 SET key value EX second 效果等同於 SETEX key second value 。
- PX millisecond :設置鍵的過期時間為 millisecond 毫秒。 SET key value PX millisecond 效果等同於 PSETEX key millisecond value 。
- NX :只在鍵不存在時,才對鍵進行設置操作。 SET key value NX 效果等同於 SETNX key value 。
- XX :只在鍵已經存在時,才對鍵進行設置操作。