1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
| @Slf4j public class RedisDistributedLock { private static final String REDIS_LOCK_PREFIX = "redis_lock-"; private static final int MANEUVER_SLEEP_TIME = 100; private static final String BATCH_CHECK_KEY = "batchCheckMember-"; private static final String API_CHECK_KEY = "api_key-";
private String lockKey;
private String value;
int expireTime = 10 * 1000;
int acquireTimeout = 1 * 1000;
private static final int NEVER_WAIT_LOCK_EXPIRE_TIME = 6;
private static final String COMPARE_AND_DELETE = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
private static final Long RELEASE_LOCK_SUCCESS_RESULT = 1L;
private RedisTemplate<String, String> template;
public RedisDistributedLock(RedisTemplate<String, String> template, String lockKey){ this.template = template; this.lockKey = lockKey; }
public RedisDistributedLock(RedisTemplate<String, String> template, String lockKey, int acquireTimeout) { this.template = template; this.lockKey = lockKey; this.acquireTimeout = acquireTimeout; }
public RedisDistributedLock(RedisTemplate<String, String> template, String lockKey, int acquireTimeout, int expireTime) { this.template = template; this.lockKey = lockKey; this.acquireTimeout = acquireTimeout; this.expireTime = expireTime; }
public String acquire() throws RedisDistributedLockException { long end = System.currentTimeMillis() + acquireTimeout; value = lockKey; while (System.currentTimeMillis() < end) { Boolean result = false; try { result = template.opsForValue().setIfAbsent(lockKey ,value, expireTime, TimeUnit.MILLISECONDS); } catch (Exception e) { log.error("acquire lock due to error ", e); throw new RedisDistributedLockException(ResponseCode.REDIS_LOCK_ACQUIRE_FAILED); } if (result) { log.info("{} acquire lock", lockKey); return value; } try { Thread.sleep(MANEUVER_SLEEP_TIME); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } return null; }
public boolean release() throws RedisDistributedLockException { if(value == null){ return false; } List<String> keys = Collections.singletonList(lockKey);
try { DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(COMPARE_AND_DELETE, Long.class); Long result = template.execute(redisScript,keys, value); log.info("结果 {}", result); if (Objects.equals(result, RELEASE_LOCK_SUCCESS_RESULT)){ log.info("{} release lock", lockKey); return true; } }catch (Exception e){ throw new RedisDistributedLockException(ResponseCode.REDIS_LOCK_RELEASE_FAILED); } return false; }
public String aquireNeverWaitLock(){ Boolean result = false; value = lockKey; try { result = template.opsForValue().setIfAbsent(lockKey ,value, NEVER_WAIT_LOCK_EXPIRE_TIME, TimeUnit.HOURS); } catch (Exception e) { log.error("acquire lock due to error ", e); throw new RedisDistributedLockException(ResponseCode.REDIS_LOCK_ACQUIRE_FAILED); } if (result){ return lockKey; } return null; }
public static String generateKey(Integer propertyId, String openId){ return REDIS_LOCK_PREFIX + propertyId + "-" + openId; }
public static String generateBatchKey(int propertyId){ return REDIS_LOCK_PREFIX + BATCH_CHECK_KEY + propertyId; }
public static String generateApiKey(int propertyId, List<String> param){ if (null == param || param.size() <= 0){ throw new ParameterException(ResponseCode.PARAMETER_NULL_EXCEPTION); } StringBuilder ids = new StringBuilder(); for (String oneId : param) { ids.append(oneId); } String finalStr = ""; log.info("origin param : {}", ids.toString()); if (ids.length() > 32){ finalStr = DigestUtils.md5DigestAsHex(ids.toString().getBytes()); }else{ finalStr = ids.toString(); } return REDIS_LOCK_PREFIX + API_CHECK_KEY + propertyId + "_" + finalStr; } }
|