2024-09-08-服務端開發實戰

解決方案.gif

典型冪等策略

冪等處理的一般流程.png

唯一索引策略(極少使用)

1.select+insert+唯一索引沖突

//1.根據冪等號查詢冪等記錄
Record record = dao.select(param);
if (record != null){
//2.冪等記錄存在,直接返回冪等結果或根據記錄狀態(如失敗可重試)進一步處理
}else{
    try{
        //3.冪等記錄不存在,插入冪等記錄
        dao.insert(entity);
        //4.插入成功,執行業務邏輯
    }catch(DuplicateKeyException e){
        //5/插入失敗,若為重復異常,直接返回冪等結果或進一步處理
        record = dao.select(param);
        //6.處理邏輯
    }catch(Throwable tr){
        //7.其他異常處理邏輯
    }
}

2.insert+唯一索引沖突

//1.插入冪等記錄
try{
    //2.插入成功,執行業務邏輯
    dao.insert(entity);
}catch(DuplicateKeyException e){
    //3.插入失敗且為重復異常,直接返回冪等結果或進一步處理
    dao.select(param);
    //4.處理邏輯
}catch(Throwable tr){
    //5.其他異常處理邏輯
}

數據庫開銷大,如果重復請求發生的概率較小,可優先選擇2.insert+唯一索引沖突。

唯一索引需結合冪等記錄狀態變更管控+事務機制(數據庫事務/分布式事務)+鎖機制。

悲觀鎖策略(金融賬務清算域常用方式)

//1.開啟事務
begin;
//2.基于冪等號 biz_no 鎖行查詢
record = select * from table_name where biz_no='xxxx' for update
//3.沒有相關冪等記錄,說明是首次請求
if (record == null){
    //4.初始化并插入冪等記錄
    insert(init(param))
    //5.再次基于冪等號biz_no鎖行查詢
    record = select * from table_name where biz_no='xxxx' for update
}

//6.鎖行查詢成功,根據記錄判斷決策處理方式
if (record.getStatus() != 預期狀態){
    //7.非預期狀態,結束處理
    return;
}

//8.預期狀態,執行業務邏輯,如查詢,更新流水等
//9.更新記錄
update table_name set status ='目標狀態' where biz_no='xxx';
//10.提交事務
commit

通過串性化實現冪等,資源占用較多
依靠數據庫自身的特性來實現,實現成本低,結合了事務機制保障了較強的數據一致性,解決了請求并發、亂序等的問題

1.查詢冪等數據的狀態,如果是不可重試終態,直接返回;
2.如果是可重試終態,則進行重試(同一冪等號),涉及到下游則需要結合分布式事務
3.插入冪等記錄TransactionTemplate REQUIRED_NEW
4.下游處理成功,則變更冪等記錄狀態
5.下游也必須是冪等的。

分布式鎖

分布式冪等.png

SETNX keyName value,若keyName已存在于Redis中,則返回0;
若不存在,則返回1.

//1.嘗試將keyName寫入緩存
if(redis.setNx(keyName, 1) == 1){
    //2.寫入成功,即獲取鎖成功,繼續執行業務邏輯
    //3.執行完成,釋放鎖(為了防止誤釋放,可采用LUA腳本)
}else{
    //4.寫入失敗,即獲取鎖失敗,要么直接返回,要么等待、重試
}

需結合事務機制和重試機制形成完整方案。
事務機制用于保證業務邏輯的數據一致性;重試機制是基于持久化的冪等記錄進行失敗重試,保證最終一致性。
還存在釋放鎖操作可能失敗的情況。一旦釋放鎖操作失敗,就會導致一段時間內記錄一直在緩沖中,其他線程無法獲得鎖。
即使設置了失效時間,在有效期內仍會存在問題。失效時間過短,業務邏輯執行完前釋放鎖,失效時間過長,其他嘗試獲取鎖的過程就需要等待,甚至可能超時。

解決冪等問題的關鍵

  • 1.唯一性約束
  • 2.執行唯一性檢查

解決冪等問題的實現方式
唯一索引:數據庫唯一索引,唯一索引可以基于業務流水建立,也可以單獨建表實現;
唯一數據:悲觀鎖、樂觀鎖、分布式鎖等鎖機制;
狀態機約束:對于存在狀態流轉的業務,通過狀態機的流轉約束,可以實現有限狀態機的冪等。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,720評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,690評論 2 370

推薦閱讀更多精彩內容