redis分布式鎖實現
做項目時遇到一個功能,需要3步,1)通過solr取一個已審核數,然後和可通過數進行比較 2)更新資料庫審核狀態 3)更新solr已審核數 ,這時遇到一個問題,就是當用戶進行批量審核的時候,這時比如有10個品被審核,那這10個請求可能會被同時打到10個機器上,然後同時執行上段代碼(1,2,3步),這時就有可能出現高並發的問題,比如現在已經審核了9個商品,然後最多審核10個,兩個請求同時進來,第一個請求讀取到的是9,然後開始執行2和3步,結果還沒執行完3,第二個請求就進來了,這時他讀到的也是9(由於還沒重刷solr),所以就會導致多審核了一個商品。
由於是多台機器並發問題,所以不能只用Synchroinzed這種,故這裡採用分布式鎖方式。
String lockKey = null;
if(RoutineType.SEC_KILL.isEqual(activity.getRoutineType)){ //秒殺頻道
CheckGroup group = routineCheckGroupService.getCheckGroupByErpPin(activity.getChannelID,erpPin);
if(group!=null && pageView.getRoleType!=1 && routineCheckGroupService.isLeafCheckGroupUser(group.getId)){ //如果是末級審核組,roleType=1為運營審核
lockKey = this.acquireCheckLock(group.getId, applyWare.getBatchId);
int allCanAssign = queryAssignedBatchResourceCount(group.getId, applyWare.getBatchId);//查詢審核組在當前批次上已分配到的資源數
int hasPassed = checkActivityService.queryHasPassedNum(Arrays.asList(group.getId), applyWare.getBatchId);
LogTypeEnum.ROUTINE_CHECK_RECOMMEND.warn("passApply hasPassed:{}, allCanAssign:{}", hasPassed, allCanAssign);
if(hasPassed + 1 > allCanAssign){
result.setSuccess(false);
result.setResultCode("當前批次可審核通過"+ allCanAssign +"條,已審核通過" + hasPassed + "條,通過數量超過最大限制!");
return result;
}
}
}
this.releaseCheckLock(lockKey);//釋放分布式鎖
/**
* 獲得審核操作時的分布式鎖
*/
private String acquireCheckLock(final Long checkGroupId, final Long batchId) {
String lockKey = "Check_Lock_" + checkGroupId + "_" + batchId;
int tryTimes = 0;
while(true) { //如果沒獲得鎖,會一直循環,直到超過60次
int lockSeconds = 120;//120秒後過期, 在業務執行完成後會主動刪除鎖
if (redisClient.setnx(lockKey, "1") > 0) {//鎖不存在,則獲取鎖成功
redisClient.expire(lockKey, lockSeconds);
LogTypeEnum.ROUTINE_CHECK_RECOMMEND.warn("審核操作獲得鎖lockKey:{}, tryTimes:{}", lockKey, tryTimes);
break;
}
tryTimes ++;
try {
if (redisClient.ttl(lockKey) < 0) {//防止上一操作加鎖成功,但設置過期語句執行失敗; [當 key 存在但沒有設置剩餘生存時間時,返回 -1]
redisClient.expire(lockKey, 1);//迅速過期
}
LogTypeEnum.ROUTINE_CHECK_RECOMMEND.warn("審核操作沒有獲得鎖 lockKey:{}, tryTimes:{}", lockKey, tryTimes);
Thread.sleep(2000);//休眠 2 秒
} catch (InterruptedException e) {
}
if (tryTimes > 60) {
throw new RuntimeException("審核操作等待超時!");
}
}
return lockKey;
}
/**
* 釋放審核操作時獲得的分布式鎖
*/
private void releaseCheckLock(final String checkLock) {
if (checkLock != null) {
redisClient.del(checkLock);
}
}
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
※擁抱Node.js 8.0,N-API入門極簡例子
※vuex所有核心概念完整解析State Getters Mutations Actions
※Oracle體系結構之進程
※ProxySQL 介紹
TAG:達人科技 |
※Redisson是如何實現分散式鎖的?
※使用redis實現分散式鎖實踐
※python 實現redis訂閱發布功能
※分散式框架spring-session實現session一致性使用問題
※Python+Memcached:在分散式應用程序中實現高效緩存
※Pytorch實現Logistic回歸二分類
※Python + Memcached:在分散式應用程序中實現高效緩存
※redis緩存和cookie實現Session共享
※Python + Memcached: 在分散式應用程序中實現高效緩存
※Python yield與實現
※jacoco與jenkins集成實現代碼覆蓋率分析
※ThreadLocal實現原理詳解
※東芝公司發布NVMe over Fabrics存儲節點軟體實現方案
※扒一扒 Lifecycle 的實現
※Occipital推出MR創作工具Bridge Engine,實現密實3D映射
※MapReduce設計與實現
※用TensorFlow Estimator實現文本分類
※PS4終於實現了Fortnite cross-play功能
※Prometheus+Grafana實現監控系統
※ArrayList,LinkedList,Vector基本原理與實現