解決高併發環境下數據插入重複問題

背景描述

應用框架:Spring Boot + mybatis
數據庫:Sqlserver
系統一個業務號只允許存在一筆正在處理的預約訂單,當多個用戶同時發送多筆業務號相同的預約訂單,我們發現數據庫中也會存在多筆業務號相同的預約訂單。。按照程序的編寫邏輯,重複的數據應當是會被判斷出來不被存儲的。


1.原因分析

由於短時間內客戶可能連續推送了兩條重複的數據,兩條數據時間間隔非常小,因此導致了我們的

if(業務號存在){
   // ...
}

否則訂單入庫

if 裏面操作還沒有執行完畢,第二條擁有相同數據的線程已經進入並通過了if的檢驗,導致數據庫存儲了兩條相同的數據。


2.解決方法

(1)使用synchronized同步代碼塊即加同步鎖
synchronized(this){
   //...
}

這樣會導致其他正常數據的推送線程也被阻塞,影響效率。因此不採用。我們考慮只對重複數據加鎖。

String lonNbr=... ;
synchronized(lonNbr.intern()) {
    //...
}   

使用String作爲同步鎖必須注意產生不同對象的問題,必須保證線程拿到的是同一個String對象,但這個有時很難保證。這個時候就得使用intern()方法,這樣就是直接獲取的是字符串的值本身,而不是取的String的對象。
Java中String做爲synchronized同步鎖使用詳解

這種加同步鎖的方法在負載均衡下的多臺應用服務器會失效!

(2)分佈式鎖

基於數據庫實現分佈式鎖;(唯一索引,事務隔離級別,鎖)
基於緩存(Redis等)實現分佈式鎖;
基於Zookeeper實現分佈式鎖;

分佈式鎖簡單入門以及三種實現方式介紹

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章