背景描述:
公司是做網際網路借貸業務的,前段時間對接了乙個第三方平台,為該平台的使用者提供現金借貸業務。但是,剛上線便發現存在乙個很嚴重的問題,就是在短時間內(毫秒級)同乙個使用者生成了多筆借款,我們的業務場景是要求同乙個使用者針對同一類借款,只可以存在一筆待還借款。經過排查發現第三方平台每次都會在同一時間傳送多次相同的借款請求(其實就是第三方平台沒有控制好邏輯,極短時間內對使用者的同乙個借款請求多次重試引起的)。查出問題後便立即通知第三方平台排查問題,防止使用者的重複提交,並控制好伺服器重試機制的頻率,但是顯然我們平台的安全性不能夠依賴第三方去實現。
針對該問題,想到了三個解決辦法:
1. 在應用中通過快取實現乙個類似鎖的功能
2. 在資料庫中實現分布式鎖
3. 使用redis實現分布式鎖
第一種方式,在應用中通過快取來實現,將會占用應用伺服器的大量快取,而且在分布式部署的場景下,顯然無法解決該問題。
第二種方式,資料庫中儲存借款鎖,此方法可行,但是關係型資料庫的效能始終是個問題,當請求量大了之後將會成為系統的瓶頸。
經過考量,最終選擇redis分布式鎖來實現借款邏輯的序列處理。
**實現(敏感資訊處理過,日誌列印也剔除,簡化**):
/***@title使用者借款序列執行,
redis
鎖控制,利用spring aop 實現 */
@aspect
@order(1)
@component
public
classcustborrowlockaspectextendswriteresult
/**
* 提供給自身平台借款的介面,方法
是借款入口(
rest
風格) */
public
void
}publicobjectdoborrow4channel(proceedingjoinpointpjp)throwsthrowable
publicthrowable
publicobjectdoborrow(proceedingjoinpointpjp, stringintface,stringcustidkey,booleanisreturnstring)
throwsthrowable
result = pjp.proceed();//
執行借款相關邏輯
returntojsonstr(result,false);
}catch(throwablee)finally}}
/**
* 將物件轉換為
json
字串 */
privateobject tojsonstr(objectjsonresult,booleanisreturnstring)
/**
* 解析使用者id
*/ privatestring getcustid(objectparamobj,stringuserkey)
cid =cid.trim();
if(cid.length()==0)
returncid;}}
/*** redis鎖幫助類(操作基於springframework.data.redis)
*/@component("redislockhelper")
public class redislockhelper
//未獲取到鎖則ttl檢查過期時間(防止setnx、expire間的崩潰)
long checkexpire=connection.ttl(lockbytes);
if(checkexpire == -1), expire={}]", lockname, expire);
}return 0l;//不做排隊處理,直接返回失敗
}});
return (rs==1l);
} catch (exception e)
return false;
}public void unlock(final string lockname) catch (exception e) }}
總結:1.為了降低**耦合性,使用了spring aop,防止修改原有**。
2.使用redis實現分布式鎖,達到分布式部署場景下使用者借款序列處理(防止產生多筆重複借款)。
不足:當redis伺服器宕機之後,將會導致所有借款都被阻塞,因此後期可以考慮部署redis集群。
分布式鎖以及分布式鎖在專案中的使用總結
第一 基於資料庫 第二 基於快取 第三 基於zookeeper 要實現分布式鎖,最簡單的方式可能就是直接建立一張鎖表,然後通過操作該表中的資料來實現了。當我們要鎖住某個方法或資源時,我們就在該表中增加一條記錄,想要釋放鎖的時候就刪除這條記錄。create table methodlock id in...
分布式快取Redis應用場景解析
redis的應用場景非常廣泛。雖然redis是乙個key value的記憶體資料庫,但在實際場景中,redis經常被作為快取來使用,如面對資料高併發的讀寫 海量資料的讀寫等。舉個例子,a 首頁一天有100萬人訪問,其中有乙個 積分 的板塊,要直接從資料庫查詢,那麼一天就要多消耗100萬次資料庫請求。...
分布式 分布式場景下面試題
redis相比memcached有哪些優勢 執行緒模型 redis 基於 reactor 模式開發了自己的網路事件處理器 這個處理器被稱為檔案事件處理器 file event handler 雖然檔案事件處理器以單執行緒方式執行,但通過使用 i o 多路復用程式來監聽多個套接字,檔案事件處理器既實現...