當前位置:
首頁 > 知識 > redis分布式鎖實現

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);
}
}

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

擁抱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基本原理與實現