1. 程式人生 > >淺析資料庫與快取的雙寫一致性問題

淺析資料庫與快取的雙寫一致性問題

快取由於其高併發和高效能的特性,在專案中被廣泛使用。讀快取流程如下圖:

雙寫一致性有以下三個要求:

  1. 快取不能讀到髒資料
  2. 快取可能會讀到過期資料,但要在可容忍時間內實現最終一致
  3. 這個可容忍時間儘可能的小

要想同時滿足上面三條,可以採用讀請求和寫請求序列化,串到一個記憶體佇列裡去,這樣就可以保證一定不會出現不一致的情況。但是,序列化之後,就會導致系統的吞吐量會大幅度的降低,要用比正常情況下多幾倍的機器去支撐線上請求。

所以,在這裡,我們討論三種常見方法:

  1. 先更新資料庫,再更新快取
  2. 先刪除快取,再更新資料庫
  3. 先更新資料庫,再刪除快取

1. 先更新資料庫,再更新快取

這種方法是大家普遍反對的,原因集中在下面兩點:

原因1:執行緒安全形度。
同時有請求A和請求B進行更新操作,那麼會出現:

  1. 執行緒A更新了資料庫
  2. 執行緒B更新了資料庫
  3. 執行緒B更新了快取
  4. 執行緒A更新了快取
    這就出現請求A更新快取應該比請求B更新快取早才對,但是因為網路等原因,B卻比A更早更新了快取。這就導致了髒資料,因此不考慮。

    "先更新快取,再更新資料庫"這種方案同理,也是造成髒資料,所以不被考慮

原因2:業務場景角度。
有如下兩點:

  1. 如果你是一個寫資料庫場景比較多,而讀資料場景比較少的業務需求,採用這種方案就會導致資料壓根還沒讀到,快取就被頻繁的更新,浪費效能。
  2. 如果你寫入資料庫的值,並不是直接寫入快取的,而是要經過一系列複雜的計算再寫入快取。那麼,每次寫入資料庫後,都再次計算寫入快取的值,無疑是浪費效能的。顯然,刪除快取更為適合。

如果一定要更新快取,可以考慮給快取資料增加版本號

2. 先刪除快取,再更新資料庫

該方案同樣會導致不一致。同時有請求A和請求B進行更新操作,那麼會出現:

  1. 請求A進行寫操作,刪除快取
  2. 請求B查詢發現快取不存在
  3. 請求B去資料庫查詢得到舊值
  4. 請求B將舊值寫入快取
  5. 請求A將新值寫入資料庫上述情況就會導致不一致的情形出現。而且,如果不採用給快取設定過期時間策略,該資料永遠都是髒資料。

解決方法:

  1. 先刪除快取
  2. 再寫資料庫(這兩步和原來一樣)
  3. 休眠一定時間(例如1秒或200ms),再次刪除快取。這麼做,可以將快取髒資料再次刪除。

然而這種解決方案由於要休眠執行緒還是很影響吞吐量的

3. 先更新資料庫,再刪除快取

這種方案是很多工程採用的方案,我們來看下是否一定安全。
假設有兩個請求,一個請求A做查詢操作,一個請求B做更新操作,那麼會有如下情形產生

  1. 快取剛好失效
  2. 請求A查詢資料庫,得一箇舊值
  3. 請求B將新值寫入資料庫
  4. 請求B刪除快取
  5. 請求A將查到的舊值寫入快取

這樣,髒資料就產生了,然而上面的情況是假設在資料庫寫請求比讀請求還要快。實際上,工程中資料庫的讀操作的速度遠快於寫操作的。
要麼通過2PC或是Paxos協議保證一致性,要麼就是想盡辦法降低併發時髒資料的概率,大概是因為2PC太慢,而Paxos又太複雜,綜合考慮,Facebook選擇了這個第三種方案。

如果刪除快取失敗了怎麼辦?

啟動一個訂閱程式去訂閱資料庫的binlog,獲得需要操作的資料。在應用程式中,另起一段程式,獲得這個訂閱程式傳來的資訊,進行刪除快取操作。

阿里開源的中介軟體canal可以完成訂閱binlog日誌的功能。

總結

本文是對目前網際網路中已有的一致性方案進行了一個總結,希望大家有所收穫。

最後,限於筆者經驗水平有限,歡迎讀者就文中的觀點提出寶貴的建議和意見。如果想獲得更多的學習資源或者想和更多的技術愛好者一起交流,可以關注我的公眾號『全菜工程師小輝』後臺回覆關鍵詞領取學習資料、進入前後端技術交流群和程式設計師副業群。同時也可以加入程式設計師副業群Q群:735764906 一起交流。

相關推薦

分散式資料庫快取一致性方案解疑

在網際網路領域,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒什麼疑問,都是按照下圖的流程來進行業務操作。但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取;又或者是先刪除快取,再更新資料庫,其實大家存在很大的爭議。目前筆者還沒有

分散式資料庫快取一致性方案解疑(轉載)

轉載路徑:https://mp.weixin.qq.com/s?__biz=MzI4NTA1MDEwNg==&mid=2650767895&idx=1&sn=eb87586d2b7748021fd8cd1791d5d39e&chksm=f3f9

Redis快取維護方案-考慮資料庫快取、redis和本地資料庫事務一致性資料庫主從同步延遲的情況怎麼解決快取資料庫不一致

一般常用的快取方案有兩種: 第一種 讀的時候,先讀快取,快取沒有的話,讀資料庫,取出資料後放入快取,同時返回響應。 更新的時候,

分散式之資料庫快取一致性方案解析(三)

作者:孤獨煙出處: http://rjzheng.cnblogs.com/ 正文 博主本來覺得,《分散式之資料庫和快取雙寫一致性方案解析》,一文已經十分清晰。然而這一兩天,有人在微信上私聊我,覺得應該要採用 先刪快取,再更新資料庫,再刪快取 這一方案作為快取更新策

分散式之資料庫快取一致性方案解析

為什麼寫這篇文章? 首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。 但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取。又或者是先刪除快取,再更新資料庫,其實大家存在

淺析資料庫快取一致性問題

快取由於其高併發和高效能的特性,在專案中被廣泛使用。讀快取流程如下圖: 雙寫一致性有以下三個要求: 快取不能讀到髒資料 快取可能會讀到過期資料,但要在可容忍時間內實現最終一致 這個可容忍時間儘可能的小 要想同時滿足上面三條,可以採用讀請求和寫請求序列化,串到一個記憶體佇列裡去,這樣就可以保證一定不會出

如何保證快取資料庫一致性

一般來說,如果允許快取可以稍微的跟資料庫偶爾有不一致的情況,也就是說如果你的系統不是嚴格要求 “快取+資料庫” 必須保持一致性的話,最好不要做這個方案,即:讀請求和寫請求序列化,串到一個記憶體佇列裡去。 序列化可以保證一定不會出現不一致的情況,但是它也會導致系統的吞吐量大幅度降低,用比正常情況下多幾倍的機器去

快取資料庫一致性 深度分析

# 前言 微笑挖坑,努力填坑。         ———— 已經擁有黑眼圈,但還沒學會小豬老師時間管理學的蠻三刀同學 我們來討論秒殺系統中**快取熱點資料**的問題,進一步延伸到資料庫和快取的雙寫一致性問題,並且給出了實現程式碼。 ## 本篇文章主要內容 - 快取熱點資料 - 為何要使用

Redis快取資料庫一致性問題:

    資料庫與快取讀寫模式策略   寫完資料庫後是否需要馬上更新快取還是直接刪除快取?   (1)、如果寫資料庫的值與更新到快取值是一樣的,不需要經過任何的計算,可以馬上更新快取,但是如果對於那種寫資料頻繁而讀資料少的場景並不合適這種解決方

Redis使用總結(二、快取資料庫一致性問題)

首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取。又或者是先刪除快取,再更新資料庫,其實大家存在很大的爭議。目前沒有一篇全面的部落格,

資料庫快取一致性策略

問題:怎麼保持快取與資料庫一致? 要解答這個問題,我們首先來看不一致的幾種情況。我將不一致分為三種情況: 1. 資料庫有資料,快取沒有資料; 2. 資料庫有資料,快取也有資料,資料不相等; 3. 資料庫沒有資料,快取有資料。 大多數人使用的策略,叫做 Cache Asi

redis和資料庫一致性問題

   一致性問題是分散式常見問題,還可以再分為最終一致性和強一致性。資料庫和快取雙寫,就必然會存在不一致的問題。答這個問題,先明白一個前提。就是如果對資料有強一致性要求,不能放快取。我們所做的一切,只能保證最終一致性。     從理論上來說,給快取設定過期時間,是保證最終一

redis系列之資料庫快取資料一致性解決方案

資料庫與快取讀寫模式策略 寫完資料庫後是否需要馬上更新快取還是直接刪除快取? (1)、如果寫資料庫的值與更新到快取值是一樣的,不需要經過任何的計算,可以馬上更新快取,但是如果對於那種寫資料頻繁而讀資料少的場景並不合適這種解決方案,因為也許還沒有查詢就被刪除

併發中如何保證快取DB一致性(JAVA栗子)

  併發場景中大部分處理的是先更新DB,再(刪緩、更新)快取的處理方式,但是在實際場景中有可能DB更新成功了,但是快取設定失敗了,就造成了快取與DB資料不一致的問題,下面就以實際情況說下怎麼解決此類問題。   名詞 Cache:本文內指redis,ReadRequest:請求從Cache、Db中拿去資料,Wr

分布式之數據庫和緩存一致性方案解析

讀寫分離 CA 試圖 並不是 設有 image 性能 stat 延時 引言 為什麽寫這篇文章? 首先,緩存由於其高並發和高性能的特性,已經在項目中被廣泛使用。在讀取緩存方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。 但是在更新緩存方面,對於更新完數據庫,是更新緩存

布式之數據庫和緩存一致性方案解析(轉)

一段時間 其他 wechat 偽代碼 sql 讀寫 適合 scene mage 引言 為什麽寫這篇文章? 首先,緩存由於其高並發和高性能的特性,已經在項目中被廣泛使用。在讀取緩存方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。但是在更新緩存方面,對於更新完數據庫,是更

redis 一致性 看一篇成高手系列 一

首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。 但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取。又或者是先刪除快取,再更新資料庫,其實大家存在很大的爭議。目前沒有一篇全面的部落格,對這幾種方案進行解

redis 一致性

首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。 但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取。又或者是先刪除快取,再更新資料庫,其實大家存在很大的爭議。目前沒有一篇全面的部落

如何保證db快取的資料一致性

為了提升效能,快取在系統開發中具有普遍的應用。常見的模式是先查詢/更新db後再去更新快取,那麼如何保證db和快取的資料一致性的問題是實際開發中經常遇到的問題。這種場景下容易造成資料不一致的問題主要是快取雙寫。 一、快取雙寫問題 先查詢或者更新db,然後再更

【Redis】- 一致性

  好好學習,天天向上!   【Redis】- 雙寫一致性 首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。 但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取。又或