欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

系統(tǒng)高吞吐量下的數據庫重復寫入問題分析解決

 更新時間:2022年04月22日 15:43:57   作者:zziawan  
這篇文章主要介紹了系統(tǒng)高吞吐量下的數據庫重復寫入問題分析解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

問題分析

為了提高系統(tǒng)的吞吐量,很多環(huán)節(jié)下對于數據庫的寫入是多線程,甚至是多進程的。為了保證寫入成功,在很多情況下需要多次重試。這就會帶來一個問題,數據重復,同一條數據會被記錄多次。有些情況下數據重復無傷大雅,但是很多情況系統(tǒng)是無法容忍數據重復的。因此這個問題需要解決。我個人覺得解決這一問題有兩個方向:第一,從數據庫上保證數據不重復,第二,從程序上保證數據不重復。

數據庫上解決

主要包括:主鍵,唯一性索引,甚至是臨時表。程序上解決無非就是要保證同步,這兩種方式能解決很多情況下的數據重復。但是有些情況可能比較棘手,使用者兩種方法有時并不能很好的解決,或實現起來比較復雜,如下面的數據

假如下表主要字段如下:

id  studentId  teacherId  states 

狀態(tài)(states)是有多種的(0,1,2,3),狀態(tài)可以轉換,但是狀態(tài)為,0的一個只能由一個,其它字段是可以重復的。這個其實就是保證某一種狀態(tài)下的數據不重復。

首先唯一性索引不能夠起作用,因為無法建立唯一性索引。主鍵也沒有效果,沒法通過這些字段生成可區(qū)分的id。所以這兩種方法都失效了。還有一種方法就是臨時表,在臨時表中插入一條能夠區(qū)分的數據(比如studentId,teacherId組合),無論是唯一索引還是主鍵都可以。寫入時首先寫臨時表,臨時表寫入成功則插入一條數據,然后清空臨時表。這在嚴格保證數據不重復的情況下是能夠起作用的,但是比較繁瑣,需要處理一個臨時表。

另外的一個辦法就是根據我們的業(yè)務場景,在一個時間段內(比如1分鐘)不會出現兩條相同數據寫入。這樣我們可以使用studentIdTeacherid加上精確到分鐘的時間來構成一個唯一id,重試時間間隔一般都極短(秒級別),這樣通過id來保證數據的唯一性。

從程序上保證數據不重復

如果從程序上來保證數據不重復,則更加復雜。第一種辦法是對寫入過程加鎖,確保只有一次寫入成功代碼如下(偽代碼):

Lock lock =new WriteLock();
public void write(Data data){
try{
     if(lock.tryLock() ){
               dataRepository.save(data);
               if(dataRepository.numberOf(data)>1){//在寫入的時候檢測如果數據庫中有該數據拋出異常。再次保證數據不重復。
                   throw new DataException
            }
      
     }  
  }finally{
     lock.unlock();
  }
}

這種方式首先會存在效率問題,所有的數據都要順序寫入會導入效率下降。我們只需要保證同一條數據不能并發(fā)寫入而不是不同數據。另外這種方式還會存在一定概率的重復,因為網絡問題和數據庫或ORM框架的緩存問題,會導致寫入檢測時并不能發(fā)現數據庫的更新。比如使用hibernate,兩次線程調用write方法會使用兩個session,從而使得第一次寫入緩存的數據無法在下一次操作中看到。在write方法中多次調用numberOf方法也是不起用的,由于session的緩存,后面的查詢會使用第一次的緩存結果,在第一次查詢后的數據庫變化,后面的查詢仍然無法覺察。

針對寫入效率低的問題,這里可以采用數據鎖,即通過一種方法比如使用data的hashcode來映射來獲取鎖,這樣不同的數據會獲取到不同的鎖,解決了所有數據的順序寫入問題。但是跟第一種情況一樣仍會存在數據重復問題。

對于多進程的情況,如微服務部署多個的情況,上面的同步會失效。對于這種情況唯一的解決辦法就是使用上面所說的數據庫同步或者構造一個環(huán)節(jié)鎖,類似于令牌的方法。只有獲取到令牌才有寫入資格,寫入成功后銷毀針對該數據的“令牌“。這種實現其實也比較簡單,如使用一個redis的hashmap,每次寫入首先獲取該數據對應的value,通過value來判斷該數據是否寫入,來保證數據不重復。

總結

上面無論哪種方法,針對本文所提到的數據,解決重復問題都是不容易的。要么實現起來比較復雜,要么還是不能100%保證數據不重復。針對我們的業(yè)務場景:state為0的狀態(tài)下數據能有一條,且0的狀態(tài)不會持續(xù)太久,后面的操作會將其修改。而且多線程重試并不是每次都發(fā)生的,多進程情況下,每次數據寫入也多是只通過其中一個節(jié)點,針對這種情況其實可以采取更簡單的處理方式,不做過多的順序限制只在寫入時檢查數據庫,如果真的因為數據更新或者并發(fā)導致了多次寫入也沒有關系(這種情況很少),后續(xù)的操作時再刪除多寫入的數據。這是一種樂觀的處理方式,但是對于很多情況是可以解決數據重復問題的。

以上是我個人對于只有某種狀態(tài)的數據不能重復寫入問題的處理方法的思考。主要是從數據庫和程序上來控制及如果場景允許使用樂觀(后續(xù)補救)的方法。僅供參考,更多關于高吞吐量系統(tǒng)的數據庫重復寫入解決的資料請關注腳本之家其它相關文章!

相關文章

  • Navicat連接虛擬機mysql常見錯誤問題及解決方法

    Navicat連接虛擬機mysql常見錯誤問題及解決方法

    這篇文章主要介紹了Navicat連接虛擬機mysql常見錯誤問題及解決方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • MySQL實現查詢處理JSON數據的示例詳解

    MySQL實現查詢處理JSON數據的示例詳解

    這篇文章主要為大家詳細介紹了MySQL如何實現查詢處理JSON數據,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以了解一下
    2023-06-06
  • mysql中binlog_format模式與配置詳細分析

    mysql中binlog_format模式與配置詳細分析

    這篇文章主要介紹了mysql中binlog_format模式與配置的相關內容,詳細介紹了binlog的三種格式與SBR、 RBR 兩種模式各自的優(yōu)缺點,需要的朋友可以參考。
    2017-10-10
  • MySQL 8忘記密碼的最佳處理方式淺析

    MySQL 8忘記密碼的最佳處理方式淺析

    這篇文章主要給大家介紹了關于MySQL 8忘記密碼的處理方式,文中通過圖文介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-02-02
  • mysql臟頁是什么

    mysql臟頁是什么

    本文主要介紹了什么是mysql臟頁,為什么會出現臟頁,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-07-07
  • MySQL開啟遠程訪問權限的最新方法

    MySQL開啟遠程訪問權限的最新方法

    這篇文章主要給大家介紹了關于MySQL開啟遠程訪問權限的最新方法,在MySQL中,要實現遠程訪問,首先需要在MySQL服務端上開啟相應的權限,需要的朋友可以參考下
    2023-08-08
  • MySQL連接異常:Communications link failure問題及解決

    MySQL連接異常:Communications link failure問題及解決

    這篇文章主要介紹了MySQL連接異常:Communications link failure問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • MySql三種避免重復插入數據的方法

    MySql三種避免重復插入數據的方法

    這篇文章主要介紹了MySql三種避免重復插入數據的方法,幫助大家更好的理解和使用MySQL數據庫,感興趣的朋友可以了解下
    2020-09-09
  • MySQL中select...for update鎖表

    MySQL中select...for update鎖表

    select…for update在MySQL中,是一種悲觀鎖的用法,一般情況下,會鎖住一行數據,但如果沒有使用正確的話,也會把整張表鎖住,本文就來介紹一下,感興趣的可以了解一下
    2023-10-10
  • MySQL修煉之聯結與集合淺析

    MySQL修煉之聯結與集合淺析

    在mysql中,最重要的就是查詢了,下面這篇文章主要給大家介紹了關于MySQL修煉之聯結與集合的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-09-09

最新評論