redis實現分布式鎖來防止重復提交問題(redis鎖)


1、何為重復提交
重復提交是在第一次請求已經在進行處理或處理成功的情況下,人為的進行多次操作,導致不滿足冪等要求的服務多次改變狀態。

2、何為冪等
冪等是其任意多次執行所產生的影響均與一次執行的影響相同(不用擔心重復執行會對系統造成改變)。

3、何時使用

場景一:在網絡延遲的情況下讓用戶有時間點擊多次submit按鈕導致表單重復提交

場景二:表單提交后用戶點擊【刷新】按鈕導致表單重復提交

場景三:用戶提交表單后,點擊瀏覽器的【后退】按鈕回退到表單頁面后進行再次提交

4、造成影響

 因為接口重復提交,會造成臟數據,進而導致數據被覆蓋或有多筆業務數據問題。

5、實現思路

這里我們用到Redis的SET命令

set(key,value,"NX","EX",expireTime);
//NX:表示如果key不存在,則設置key-value,否則返回null。
//EX:過期時間的單位/秒。

首先找到防止重復提交的標識信息,把參數組裝好,這里可以使用MD5加密key,這樣重復提交的請求生成的key就是一樣的。請求前先獲取鎖,

請求結束后必須釋放鎖,同時我們設置鎖的過期時間,可以有效防止死鎖。

6、實現代碼

//獲取分布式鎖
public synchronized boolean getRedisLock(String lockKey,String value,long expireTime){

String result=jedisCluster.set(lockKey,value,"NX","EX",expireTime);//單位秒
if("OK".equalsIgnoreCase(result)){
return true;
}else{
return false;
}
}

//釋放分布式鎖
public boolean releaseRedisLock(String lockKey,String value){
String script="if redis.call('get',KEYS[1])==ARGV[1] then redis.call('del',KEYS[1]) else return 0 end";
String result=jedisCluster.eval(script,Collections.singletonList(lockKey),Collections.singletonList(value));
if(1L==(Long)result){
return true;
}else{
return false;
}
}

//使用分布式鎖

String key="xxx";
String value="xxx";
boolean lock=getRedisLock(key,value,2*60);//默認兩分鍾 
try{
if(lock){
//數據保存邏輯
}else{
//重復提交提示
}
}
catch(Exception e){
}finally{
releaseRedisLock(key,value);//釋放鎖
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM