redisを使用して高同時シーンを処理する
7288 ワード
1.原理:同じユーザがロックを取得すると、そのユーザは常にロックを保持する.同じユーザが再び取得すると,原子性に基づいてlockはtrueを返す.
転載先:https://www.cnblogs.com/thinkingandworkinghard/p/10627994.html
/**
* ( ), 2
*/
public boolean lock(){
return lock(GETLOCK_TIMEOUT/1000);
}
/**
* ( ), timeoutSeconds
*/
public boolean lock(int timeoutSeconds){
int timeout = timeoutSeconds*1000;
while (timeout >= 0) {
// JVM , : LOCK_EXPIRE_TIMEOUT ,
if(LOCKED_NAMES.contains(lockname)){
int sleeptime = random.nextInt(100)+100;
try{Thread.sleep(sleeptime);} catch (InterruptedException e) {}
timeout -= sleeptime;
continue;
}
// , : ( ) LOCK_EXPIRE_TIMEOUT , ( )
String hearbeatFlag = RedisCacheUtil.get(lockname + HEARTBEAT_SUFFIX , String.class );
if(hearbeatFlag!=null){
int sleeptime = random.nextInt(100)+100;
try{Thread.sleep(sleeptime);} catch (InterruptedException e) {}
timeout -= sleeptime;
continue;
}
//
long expires = System.currentTimeMillis() + LOCK_EXPIRE_TIMEOUT + 1;
boolean ok = setNX(expires);
if (ok) {
//System.out.println(Thread.currentThread().getName()+": , setNX");
LOCKED_NAMES.add(lockname);
locked = true;
return locked;
}
//
RedisLockValue redisLockValue = get();
if (redisLockValue != null && redisLockValue.getExpireTime() < System.currentTimeMillis()) {
// getSet
RedisLockValue oldRedisLockValue = getSet(expires);
//
if (oldRedisLockValue != null && oldRedisLockValue.getToken().equals(redisLockValue.getToken())) {
//System.out.println(Thread.currentThread().getName()+": , getSet");
LOCKED_NAMES.add(lockname);
locked = true;
return locked;
}
}
//
int sleeptime = random.nextInt(100)+100;
try{Thread.sleep(sleeptime);} catch (InterruptedException e) {}
timeout -= sleeptime;
}
// , , GET ,
try{Thread.sleep(300);} catch (InterruptedException e) {}
RedisLockValue redisLockValue = get();
if(redisLockValue==null){
//
LOCKED_NAMES.remove(lockname);
RedisCacheUtil.delete(lockname);
RedisCacheUtil.delete( lockname + HEARTBEAT_SUFFIX );
}
return locked;
}
転載先:https://www.cnblogs.com/thinkingandworkinghard/p/10627994.html