天天看點

緩存與資料庫一緻性前言一、緩存是什麼?為什麼引入緩存?二、緩存一緻性總結

緩存與資料庫一緻性

  • 前言
  • 一、緩存是什麼?為什麼引入緩存?
    • 1.緩存的引入
    • 2.讀寫的性能提升
  • 二、緩存一緻性
    • 1.談談一緻性
    • 2.三種經典的緩存模式
    • 3.讨論三種資料更新方案
  • 總結

前言

面試的時候被問到了不少關于緩存的問題,而緩存的一緻性問題是被問的最多的,當時沒怎麼答好,這次把關于緩存的問題都記錄下來,以做積累和沉澱。

參考文檔:https://mp.weixin.qq.com/s/urm2W1rBmIGa09w8K-hqvA

https://mp.weixin.qq.com/s/a4FRIKu1YWftnso2iBvWSw

一、緩存是什麼?為什麼引入緩存?

緩存的本質:彌補cpu的高算力和IO的慢讀寫之間巨大的鴻溝。

1.緩存的引入

  1. 在初期業務量小的時候,資料庫能承擔讀寫壓力,應用可以直接和DB互動,架構簡單且強壯。
  2. 當業務量大規模增加時,DB查詢壓力和耗時都在增長。此時引入分布式緩存,減少DB壓力的同時,還提供了高qps。
  3. 發展到後面,分布式緩存也成為瓶頸,高頻的qps成為負擔,另外緩存驅逐(緩存淘汰)和網絡抖動會影響系統的穩定性,此時引入本地緩存,可以減輕分布式緩存的壓力,并減少網絡和序列化開銷。

2.讀寫的性能提升

  • 讀優化:當請求命中緩存後,可直接傳回,進而略過IO讀取,減小讀的成本。
  • 寫優化:将寫操作在緩沖中合并,讓IO裝置可以批量處理,減小寫的成本。

二、緩存一緻性

1.談談一緻性

一緻性分為三種類型:

  • 強一緻性:這種一緻性級别是最符合使用者直覺的。它要求系統寫入什麼,讀出來就是什麼,使用者體驗好,但是實作起來對系統的性能影響大。【CAP理論】
  • 弱一緻性:這種級别限制了系統在寫入成功後,不保證立即可以讀到寫入的值,也不保證多久之後資料能夠達到一緻,但會盡可能保證某個時間級别後,資料能夠達到一緻狀态。
  • 最終一緻性:最終一緻性是弱一緻性的一個特例,系統會保證在一定時間内,能夠達到資料一緻的狀态。業界大型系統較推崇的一種方式。

2.三種經典的緩存模式

有三種經典的緩存模式:

  • cache-aside
  • read/write through
  • write behind

cache-aside

  1. 讀請求流程:
    緩存與資料庫一緻性前言一、緩存是什麼?為什麼引入緩存?二、緩存一緻性總結
  2. 寫請求流程:
    緩存與資料庫一緻性前言一、緩存是什麼?為什麼引入緩存?二、緩存一緻性總結

    資料更新的時候,是先更新資料庫,再删除緩存。

    這樣操作的原因在後面會解釋。

  3. 缺點:更新頻繁的場景會導緻緩存頻繁的被删除,降低了緩存的作用
  4. 适用場景:用于讀較多的場景

read/write through

read/write through的流程和cache aside流程一緻,隻不過中間多了一個緩存元件。

1.讀請求流程:

緩存與資料庫一緻性前言一、緩存是什麼?為什麼引入緩存?二、緩存一緻性總結

先查詢緩存中資料是否存在,如果存在則直接傳回,如果不存在,則由緩存元件負責從資料庫中同步加載資料。

2.寫請求流程:

緩存與資料庫一緻性前言一、緩存是什麼?為什麼引入緩存?二、緩存一緻性總結

由緩存元件完成資料源和緩存資料的更新。

write behind

write behind與read/write through有很多相似的地方,都是緩存元件來負責緩存和資料庫的讀寫。不同在于,read/write through是同步更新緩存和資料庫的,write behind則是隻更新緩存,不直接更新資料庫,通過批量異步的方式來更新資料庫。

1.write behind流程:

緩存與資料庫一緻性前言一、緩存是什麼?為什麼引入緩存?二、緩存一緻性總結

2.缺點:緩存與資料庫的一緻性不強。

3.讨論三種資料更新方案

在資料更新的時候,有幾種選擇,選擇是先更新資料庫還是先更新緩存,然後就是是删除緩存還是更新緩存,下面分别就這三種情況進行讨論。

先更新資料庫,再更新緩存

1.問題

1、線程A更新了資料庫

2、線程B更新了資料庫

3、線程B更新了緩存

4、線程A更新了緩存

這就出現請求A更新緩存應該比請求B更新緩存早才對,但是因為網絡等原因,B卻比A更早更新了緩存。這就導緻了髒資料,是以不考慮。

2.業務考慮

1、如果是一個寫多讀少的場景,那麼就會導緻資料壓根沒有讀到,緩存就被頻繁的更新。

2、如果寫入資料庫的值,并不是直接寫入緩存的,而是要經過一系列的計算再寫入緩存,那麼,每次寫入資料庫後,都再次計算寫入緩存的值。

先删除緩存,再更新資料庫

1.問題

同時有一個請求A進行更新操作,另一個請求B進行查詢操作,那麼會出現這種情況: 1、請求A進行寫操作,删除緩存 2、請求B查詢發現緩存不存在

3、請求B去查詢資料庫得到舊值 4、請求B将舊值寫入緩存 5、請求A将新值寫入資料庫

這種其實可以通過設定過期時間解決,如果不設定,可以用延時雙删政策

1、先删除緩存

2、再寫資料庫

3、休眠一秒,再删除緩存。這樣就可以把這一秒内産生的髒資料,再次删除。

先更新資料庫,再删除緩存

假設這會有兩個請求,一個請求A做查詢操作,一個請求B做更新操作,那麼會有如下情形産生:

1.緩存剛好失效

2.請求A查詢資料庫,得一個舊值

3.請求B将新值寫入資料庫

4.請求B删除緩存

5.請求A将查到的舊值寫入緩存 ok,如果發生上述情況,确實是會發生髒資料。

然而,發生這種情況的機率又有多少呢?

發生上述情況有一個先天性條件,就是步驟(3)的寫資料庫操作比步驟(2)的讀資料庫操作耗時更短,才有可能使得步驟(4)先于步驟(5)。可是,大家想想,資料庫的讀操作的速度遠快于寫操作的(不然做讀寫分離幹嘛,做讀寫分離的意義就是因為讀操作比較快,耗資源少),是以步驟(3)耗時比步驟(2)更短,這一情形很難出現。

是以,cache aside采用了先更新資料庫,再删除緩存的方案。

總結

以上介紹了三種經典的緩存模式,同時分析了三種資料更新方案存在的問題和優缺點。

繼續閱讀