Last active
January 23, 2018 13:00
-
-
Save suyuanhxx/91bc5d70a025a72f3d064bcca5fd20ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.UUID; | |
import java.util.concurrent.TimeUnit; | |
/** | |
* Created by huangxx on 2017/6/27. | |
*/ | |
@Service | |
@Log4j2 | |
public class LockKeyService { | |
@Autowired | |
private RedisTemplate<String, String> redisTemplate; | |
private static final String LOCK_NAME = "LOCK_NAMKE:%s"; | |
@Override | |
public String getKeyByrequestId(String requestId) { | |
String identifier = acquireLockAndWait(requestId, 2, 5); | |
if (StringUtils.isNotBlank(identifier)) { | |
try { | |
secretKey = generateKey(requestId); | |
dosomething(secretKey); | |
} catch (Exception e) { | |
...... | |
} finally { | |
releaseLock(requestId, identifier); | |
} | |
} | |
return secretKey; | |
} | |
/** | |
* @param requestId | |
* @param acquireLockTimeout 获取锁超时时间 单位:s | |
* @param lockTimeout 锁过期时间 单位:s | |
* @return | |
*/ | |
private String acquireLockWithTimeout(String requestId, long acquireLockTimeout, long lockTimeout) { | |
String identifier = UUID.randomUUID().toString(); | |
String lockName = String.format(LOCK_NAME, requestId); | |
long end = System.currentTimeMillis() + acquireLockTimeout * 1000; | |
while (System.currentTimeMillis() < end) { | |
if (redisTemplate.opsForValue().setIfAbsent(lockName, identifier)) { | |
expire(lockName, lockTimeout, TimeUnit.SECONDS); | |
return identifier; | |
} | |
if (redisTemplate.getExpire(lockName) == -1) { | |
expire(lockName, lockTimeout, TimeUnit.SECONDS); | |
} | |
try { | |
Thread.sleep(500); | |
} catch (InterruptedException ie) { | |
log.error("acquireLockWithTimeout thread sleep error!", ie); | |
} | |
} | |
return null; | |
} | |
/** | |
* @param requestId | |
* @param waitTime 等待时间 单位:s | |
* @param lockTimeout 锁过期时间 单位:s | |
* @return | |
*/ | |
private String acquireLockAndWait(String requestId, long waitTime, long lockTimeout) { | |
String identifier = UUID.randomUUID().toString(); | |
String lockName = String.format(LOCK_NAME, requestId); | |
if (redisTemplate.opsForValue().setIfAbsent(lockName, identifier)) { | |
expire(lockName, lockTimeout, TimeUnit.SECONDS); | |
return identifier; | |
} | |
if (redisTemplate.getExpire(lockName) == -1) { | |
expire(lockName, lockTimeout, TimeUnit.SECONDS); | |
} | |
try { | |
Thread.sleep(waitTime * 1000); | |
} catch (InterruptedException ie) { | |
log.error("acquireLockAndWait thread sleep error!", ie); | |
} | |
return null; | |
} | |
/** | |
* 释放锁,只有锁内容符合时才会释放 | |
* | |
* @param requestId 用户id | |
* @param identifier 锁内容 | |
* @return | |
*/ | |
private boolean releaseLock(String requestId, String identifier) { | |
String lockName = String.format(LOCK_NAME, requestId); | |
while (true) { | |
if (identifier.equals(redisTemplate.opsForValue().get(lockName))) { | |
redisTemplate.delete(lockName); | |
return true; | |
} | |
break; | |
} | |
return false; | |
} | |
private String dosomething(String requestId) { | |
...... | |
} | |
private void expire(String key, long time, TimeUnit timeUnit) { | |
boolean success = redisTemplate.expire(key, time, timeUnit); | |
while(!success){ | |
success = redisTemplate.expire(key, time, timeUnit); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment