Redis分散ロックの実装およびツールクラス
7020 ワード
一、適用シーン:
本明細書で適用するシナリオは、データをクエリーする際に、データが存在しないことを発見した場合にデータベースをクエリーし、キャッシュを更新する必要があり、この場合、高同時要求が同時にデータベースにヒットする可能性があるが、この場合にはこれらの要求にロックをかけなければならないため、分散ロック方式が採用されている.(もちろん分散ロックの応用シーンが多く、本人の仕事の業務シーンに対応した処理をしただけです)
二、Redisロックのツール類:
三、業務コード:
1,redisから対応するデータを取得し,取得して直接返すと,なければ次のロックコードに進む.
2,もしロックが成功しないならば、说明はすでに后ろの业务のロジックに入ることを要求して、この时直接クライアントに帰って、待っています
3.ロックが成功した場合、データを照会してRedisを更新し、最後にロックを解除する
本明細書で適用するシナリオは、データをクエリーする際に、データが存在しないことを発見した場合にデータベースをクエリーし、キャッシュを更新する必要があり、この場合、高同時要求が同時にデータベースにヒットする可能性があるが、この場合にはこれらの要求にロックをかけなければならないため、分散ロック方式が採用されている.(もちろん分散ロックの応用シーンが多く、本人の仕事の業務シーンに対応した処理をしただけです)
二、Redisロックのツール類:
/**
* Redis
*/
@Component
public class RedisLock {
@Autowired
private RedisTemplate redisTemplate;
/**
*
* @param key
* @param value +
* @return
*/
public boolean lock(String key, String value) {
if(redisTemplate.opsForValue().setIfAbsent(key, value)) {// SETNX,setIfAbsent true, false
return true;
}
// currentValue=A value B , ( ), , “ ”
String currentValue = String.valueOf(redisTemplate.opsForValue().get(key));
//
if (!StringUtils.isEmpty(currentValue)
&& Long.parseLong(currentValue) < System.currentTimeMillis()) {
// , ,GETSET
String oldValue = String.valueOf(redisTemplate.opsForValue().getAndSet(key, value));
if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
return true;
}
}
return false;// , ,
}
/**
*
* @param key
* @param value
*/
public void unlock(String key, String value) {
try {
String currentValue = String.valueOf(redisTemplate.opsForValue().get(key));
if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
redisTemplate.opsForValue().getOperations().delete(key);
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
三、業務コード:
JSONArray allApplyForms = null;
if (this.redisActivityService.exists(RedisKeys.ApplyFormList_KEY+String.valueOf(activityId))) {
// redis , redis
Object allApplyFormsJSON = this.redisActivityService.get(RedisKeys.ApplyFormList_KEY+String.valueOf(activityId));
allApplyForms = JSONArray.fromObject(allApplyFormsJSON.toString());
} else {
long time = System.currentTimeMillis()+(20 * 1000);
if(!redisLock.lock("ApplyFormListLock", String.valueOf(time))){
return CORSUtil.getResult(0, " , ", null, callback);
}
allApplyForms = this.activityService.getAllApplyForms(activityId, thumbnailWidth,thumbnailHeight, contentCode, formTitle, flag,formModel);
if(allApplyForms ==null){
return CORSUtil.getResult(0, " ", null,callback);
}
this.redisActivityService.set(RedisKeys.ApplyFormList_KEY+String.valueOf(activityId), allApplyForms.toString(),Long.parseLong(systemConfigService.getConfig("redisOverTime"))+new Random().nextInt(200));
redisLock.unlock("ApplyFormListLock", String.valueOf(time));
}
1,redisから対応するデータを取得し,取得して直接返すと,なければ次のロックコードに進む.
2,もしロックが成功しないならば、说明はすでに后ろの业务のロジックに入ることを要求して、この时直接クライアントに帰って、待っています
3.ロックが成功した場合、データを照会してRedisを更新し、最後にロックを解除する