溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解

發(fā)布時(shí)間:2021-12-08 09:21:06 來(lái)源:億速云 閱讀:165 作者:iii 欄目:云計(jì)算

這篇文章主要介紹“數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解”,在日常操作中,相信很多人在數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

1 關(guān)于一致性

為加速系統(tǒng)性能一般都會(huì)引入緩存機(jī)制,比如 Redis。這種情況下當(dāng)用戶數(shù)據(jù)時(shí)一般會(huì)按照如下流程:

數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解  
讀流程

關(guān)于讀的流程大家是沒有異議的,但是對(duì)于數(shù)據(jù)的更新呢,如何操作才算合理呢?

 
  1. 先更新數(shù)據(jù)庫(kù)再更新緩存。

  2. 先刪緩存再更新數(shù)據(jù)庫(kù)。

  3. 先更新數(shù)據(jù)庫(kù)再刪緩存。

 

2 一致性解決方法

 

2.1 緩存TTL

簡(jiǎn)單直接又暴力的方法,如果有些數(shù)據(jù)不重要,我們讀完一次數(shù)據(jù)到緩存后設(shè)置個(gè)TTL即可,等待超時(shí)后緩存自動(dòng)從數(shù)據(jù)庫(kù)讀取下數(shù)據(jù)。

 

2.2  先更新數(shù)據(jù)庫(kù) 再更新緩存

假如我們有A、B兩個(gè)請(qǐng)求,A請(qǐng)求將age = 14,B請(qǐng)求將age = 12。我們看下正常執(zhí)行跟非正常執(zhí)行情況:

數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解  
緩存舊數(shù)據(jù)

可發(fā)現(xiàn)如果出現(xiàn)網(wǎng)絡(luò)震蕩會(huì)導(dǎo)致緩存的數(shù)據(jù)是舊數(shù)據(jù)。因此這種方法不可取。并且如果是如下場(chǎng)景也不合適:

 
  1. 寫場(chǎng)景多而讀場(chǎng)景少的業(yè)務(wù)需求,此時(shí)緩存不是經(jīng)常性的讀,卻被頻繁的更新。

  2. 如果緩存的數(shù)據(jù)是經(jīng)過各種復(fù)雜計(jì)算后寫入的,那每次寫入緩存都要運(yùn)算一次,此法不可取。

 

2.3 先刪緩存 再更新數(shù)據(jù)庫(kù)

假如A先請(qǐng)求更改數(shù)據(jù),B請(qǐng)求讀數(shù)據(jù),如果因?yàn)榫W(wǎng)絡(luò)導(dǎo)致發(fā)生如下情況也會(huì)造成緩存臟數(shù)據(jù),如果此時(shí)緩存沒有設(shè)置TTL那會(huì)一直是臟數(shù)據(jù)。

數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解  
緩存臟數(shù)據(jù)

上面這種情況如何解決呢?一般可以采用  延時(shí)雙刪策略,他的核心執(zhí)行流程如下:
public  void write(String key,Object value){
    redis.delKey(key);
    db.updateValue(value);
    Thread.sleep(1000); // 再次刪除
    redis.delKey(key);
}

該思路落實(shí)到流程圖上如下所示:

數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解  
延時(shí)雙刪策略

sleep的時(shí)間要根據(jù)業(yè)務(wù)數(shù)據(jù)邏輯耗時(shí)而定,反正目的是  確保讀請(qǐng)求結(jié)束,寫請(qǐng)求可以刪除讀請(qǐng)求造成的緩存臟數(shù)據(jù)。

當(dāng)然如果用的是主從寫讀架構(gòu),那處理思路跟上面類似,無(wú)非就是休眠時(shí)間再加上主從同步的時(shí)間即可。

數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解  
主從模式二次刪除

可是其實(shí)第二次刪除還是有不妥的地方:  

 
  1. 二次刪除前面涉及到休眠,可能導(dǎo)致系統(tǒng)性能降低,可以采用異步的方式,再起一個(gè)線程來(lái)進(jìn)行異步刪除。

  2. 如果二次刪除失敗了,還是會(huì)導(dǎo)致緩存臟數(shù)據(jù)存在的啊!

 

2.4 先更新數(shù)據(jù)庫(kù) 再刪緩存

針對(duì)緩存更新問題,老外提出了一個(gè)名為《Cache-Aside pattern》的緩存更新套路,該策略在Facebook中也廣泛使用,該策略指出:

  1. 失效:應(yīng)用程序先從緩存取數(shù)據(jù),沒有得到,則從數(shù)據(jù)庫(kù)中取數(shù)據(jù),成功后,放到緩存中。

  2. 命中:應(yīng)用程序從緩存中取數(shù)據(jù),取到后返回。

  3. 更新:先把數(shù)據(jù)存到數(shù)據(jù)庫(kù)中,成功后,再讓緩存失效。

假如此時(shí)A、B兩個(gè)線程同時(shí)請(qǐng)求,正常來(lái)講不管你是讀寫分離還是單機(jī)版,讀一般比寫快。那刪除緩存一般是有效的。

數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解  
先更新數(shù)據(jù)庫(kù)再刪除緩存

但是也有可能別的原因?qū)е伦x比寫還慢,導(dǎo)致我們刪了個(gè)  寂寞,雖然這種情況很少發(fā)生。  
 
數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解  
讀比寫還慢時(shí)

該方案相比先刪除緩存再更新數(shù)據(jù)庫(kù)還是穩(wěn)妥些的,但是也不是萬(wàn)無(wú)一失的。不管是先刪緩存再更新數(shù)據(jù)庫(kù)還是先更新數(shù)據(jù)庫(kù)再刪緩存,  如果刪除緩存失敗了都會(huì)導(dǎo)致緩存跟數(shù)據(jù)不一致問題!    

2.5 消息隊(duì)列 確保消息刪除

通過消息隊(duì)列的確認(rèn)消費(fèi)機(jī)制來(lái)刪除緩存。

數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解  
消息隊(duì)列機(jī)制確保刪除

缺點(diǎn)也很明顯:
  1. 對(duì)業(yè)務(wù)線代碼造成大量的侵入,引入了中間件。

  2. 消息的延遲刪除也會(huì)造成短暫的不一致。

 

2.6 專門程序+消息隊(duì)列 確保消息刪除

該方案啟動(dòng)一個(gè)訂閱程序去訂閱數(shù)據(jù)庫(kù)的binlog,獲得需要操作的數(shù)據(jù)。在應(yīng)用程序中,另起一段程序,獲得這個(gè)訂閱程序傳來(lái)的信息,進(jìn)行刪除緩存操作。

數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解  
專門程序刪除緩存

訂閱binlog程序在mysql中有現(xiàn)成的中間件叫  canal,可以完成訂閱binlog日志的功能。    

到此,關(guān)于“數(shù)據(jù)庫(kù)跟緩存的雙寫一致性怎么理解”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI