面試官:Redis和Mysql如何保證數(shù)據(jù)一致性?
點(diǎn)擊關(guān)注公眾號(hào):互聯(lián)網(wǎng)架構(gòu)師,后臺(tái)回復(fù) 2T獲取2TB學(xué)習(xí)資源!
上一篇:Alibaba開源內(nèi)網(wǎng)高并發(fā)編程手冊(cè).pdf
前言
1.緩存不一致是如何產(chǎn)生的
如果數(shù)據(jù)一直沒(méi)有變更,那么就不會(huì)出現(xiàn)緩存不一致的問(wèn)題。
通常緩存不一致是發(fā)生在數(shù)據(jù)有變更的時(shí)候。因?yàn)槊看螖?shù)據(jù)變更你需要同時(shí)操作數(shù)據(jù)庫(kù)和緩存,而他們又屬于不同的系統(tǒng),無(wú)法做到同時(shí)操作成功或失敗,總會(huì)有一個(gè)時(shí)間差。在并發(fā)讀寫的時(shí)候可能就會(huì)出現(xiàn)緩存不一致的問(wèn)題(理論上通過(guò)分布式事務(wù)可以保證這一點(diǎn),不過(guò)實(shí)際上基本上很少有人這么做)。
雖然沒(méi)辦法在數(shù)據(jù)有變更時(shí),保證緩存和數(shù)據(jù)庫(kù)強(qiáng)一致,但對(duì)緩存的更新還是有一定設(shè)計(jì)方法的,遵循這些設(shè)計(jì)方法,能夠讓這個(gè)不一致的影響時(shí)間和影響范圍最小化。
2.緩存更新的幾種設(shè)計(jì)
緩存更新的設(shè)計(jì)方法大概有以下四種:
先刪除緩存,再更新數(shù)據(jù)庫(kù)(這種方法在并發(fā)下最容易出現(xiàn)長(zhǎng)時(shí)間的臟數(shù)據(jù),不可?。?/span>
先更新數(shù)據(jù)庫(kù),刪除緩存(Cache Aside Pattern)
只更新緩存,由緩存自己同步更新數(shù)據(jù)庫(kù)(Read/Write Through Pattern)
只更新緩存,由緩存自己異步更新數(shù)據(jù)庫(kù)(Write Behind Cache Pattern)
接下來(lái)詳細(xì)介紹一些這四種設(shè)計(jì)方法
2.1 先刪除緩存,再更新數(shù)據(jù)庫(kù)
這種方法在并發(fā)讀寫的情況下容易出現(xiàn)緩存不一致的問(wèn)題

如上圖所示,其可能的執(zhí)行流程順序?yàn)椋?/span>
客戶端1 觸發(fā)更新數(shù)據(jù)A的邏輯
客戶端2 觸發(fā)查詢數(shù)據(jù)A的邏輯
客戶端1 刪除緩存中數(shù)據(jù)A
客戶端2 查詢緩存中數(shù)據(jù)A,未命中
客戶端2 從數(shù)據(jù)庫(kù)查詢數(shù)據(jù)A,并更新到緩存中
客戶端1 更新數(shù)據(jù)庫(kù)中數(shù)據(jù)A
可見(jiàn),最后緩存中的數(shù)據(jù)A跟數(shù)據(jù)庫(kù)中的數(shù)據(jù)A是不一致的,緩存中的數(shù)據(jù)A是舊的臟數(shù)據(jù)。
因此一般不建議使用這種方式。
2.2 先更新數(shù)據(jù)庫(kù),再讓緩存失效
這種方法在并發(fā)讀寫的情況下,也可能會(huì)出現(xiàn)短暫緩存不一致的問(wèn)題

如上圖所示,其可能執(zhí)行的流程順序?yàn)椋?/span>
客戶端1 觸發(fā)更新數(shù)據(jù)A的邏輯
客戶端2 觸發(fā)查詢數(shù)據(jù)A的邏輯
客戶端3 觸發(fā)查詢數(shù)據(jù)A的邏輯
客戶端1 更新數(shù)據(jù)庫(kù)中數(shù)據(jù)A
客戶端2 查詢緩存中數(shù)據(jù)A,命中返回(舊數(shù)據(jù))
客戶端1 讓緩存中數(shù)據(jù)A失效
客戶端3 查詢緩存中數(shù)據(jù)A,未命中
客戶端3 查詢數(shù)據(jù)庫(kù)中數(shù)據(jù)A,并更新到緩存中
可見(jiàn),最后緩存中的數(shù)據(jù)A和數(shù)據(jù)庫(kù)中的數(shù)據(jù)A是一致的,理論上可能會(huì)出現(xiàn)一小段時(shí)間數(shù)據(jù)不一致,不過(guò)這種概率也比較低,大部分的業(yè)務(wù)也不會(huì)有太大的問(wèn)題。
2.3 只更新緩存,由緩存自己同步更新數(shù)據(jù)庫(kù)(Read/Write Through Pattern)
這種方法相當(dāng)于是業(yè)務(wù)只更新緩存,再由緩存去同步更新數(shù)據(jù)庫(kù)。一個(gè)Write Through的 例子如下:

客戶端1 觸發(fā)更新數(shù)據(jù)A的邏輯
客戶端2 觸發(fā)查詢數(shù)據(jù)A的邏輯
客戶端1 更新緩存中數(shù)據(jù)A,緩存同步更新數(shù)據(jù)庫(kù)中數(shù)據(jù)A,再返回結(jié)果
客戶端2 查詢緩存中數(shù)據(jù)A,命中返回

客戶端1 觸發(fā)更新數(shù)據(jù)A的邏輯
客戶端2 觸發(fā)查詢數(shù)據(jù)A的邏輯
客戶端1 更新緩存中的數(shù)據(jù)A,返回
客戶端2 查詢緩存中的數(shù)據(jù)A,命中返回
緩存異步更新數(shù)據(jù)A到數(shù)據(jù)庫(kù)中
總結(jié)
最后,關(guān)注公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)回復(fù):2T,可以獲取我整理的 Java 系列面試題和答案,非常齊全。
正文結(jié)束
推薦閱讀 ↓↓↓ 2.Alibaba開源內(nèi)網(wǎng)高并發(fā)編程手冊(cè).pdf
5.為什么國(guó)內(nèi) 996 干不過(guò)國(guó)外的 955呢?

正文結(jié)束
2.Alibaba開源內(nèi)網(wǎng)高并發(fā)編程手冊(cè).pdf
5.為什么國(guó)內(nèi) 996 干不過(guò)國(guó)外的 955呢?

