引進(jìn)Redis(或者其他緩存)之后,應(yīng)用程序和數(shù)據(jù)持久化層多了一個(gè)中間層,部分?jǐn)?shù)據(jù)存儲(chǔ)由原來(lái)的單一持久化層,變?yōu)榫彺鎸雍统志没瘜觾煞荨?/div>
這兩部分?jǐn)?shù)據(jù)在相互同步的過(guò)程中,在某些時(shí)間點(diǎn)上的維度來(lái)看,可能會(huì)潛在不一致的情況。
其中,潛在的數(shù)據(jù)不一致,是任何一個(gè)引進(jìn)緩存層之后最面臨的最大的一個(gè)問(wèn)題(當(dāng)然兩者最終的數(shù)據(jù)是要保持一致的,這一點(diǎn)是底線)。
首先需要衡量的就是,這種潛在的不一致,會(huì)引發(fā)什么樣的問(wèn)題,帶來(lái)的問(wèn)題是否可以接受范圍之內(nèi),或者是否會(huì)對(duì)應(yīng)用程序邏輯引起致命的問(wèn)題。
緩存和持久化層存儲(chǔ)可能會(huì)不一致,往往是緩存和持久化層未同步刷新引起的,
具體舉例說(shuō)明:
第一種情況,比如點(diǎn)贊次數(shù),瀏覽次數(shù)等等(讀多寫少的場(chǎng)景,寫MySQL,讀Redis,寫入了數(shù)據(jù)庫(kù)但是尚未同步到緩存層這個(gè)間隙)。
不會(huì)對(duì)業(yè)務(wù)產(chǎn)生嚴(yán)重的邏輯錯(cuò)誤,這種暫時(shí)性的數(shù)據(jù)不一致是可以忍受的,另外就是,通過(guò)刷新等手段,兩者數(shù)據(jù)最終會(huì)達(dá)成一致。
第二種情況,比如銀行卡取款取超,導(dǎo)致余額為負(fù)數(shù),緩存和持久化層存儲(chǔ)的不一致造成嚴(yán)重的邏輯錯(cuò)誤,這種是無(wú)法忍受的。
就需要考慮這種緩存層本身的設(shè)計(jì)是否合理?
輕量級(jí)做法,代碼邏輯實(shí)現(xiàn)
如果對(duì)于緩存的合理性沒(méi)有問(wèn)題,且業(yè)務(wù)邏輯上要求緩存和持久化層強(qiáng)一致,那么久要實(shí)現(xiàn)數(shù)據(jù)庫(kù)的一致性操作。
對(duì)于緩存和持久化層數(shù)據(jù)的一致性實(shí)現(xiàn),個(gè)人的話,思路有以下兩種,
輕量級(jí)的做法如下:
對(duì)于引起數(shù)據(jù)變化的邏輯,一般都是“寫操作”,比如對(duì)數(shù)據(jù)的update或者delete,
1,首先去delete緩存中對(duì)應(yīng)的數(shù)據(jù)(而不是去對(duì)應(yīng)的update、delete,為什么?因?yàn)橹灰猟elete成功,緩存被清理之后,就消除了不一致的可能性,或者并發(fā)造成的數(shù)據(jù)覆蓋錯(cuò)誤(update),而非update就做不到),如果執(zhí)行成功,再去操作持久化層的數(shù)據(jù)庫(kù)。
2,對(duì)于insert操作,保證寫持久化庫(kù)成功,異步寫緩存(而不用刻意關(guān)注是否寫成功)。
重量級(jí)分布式鎖實(shí)現(xiàn),雙寫實(shí)現(xiàn)強(qiáng)一致
雙寫的安全性一般要通過(guò)分布式鎖來(lái)實(shí)現(xiàn),分布式鎖可以通過(guò)zookeeper或者redis實(shí)現(xiàn)。
一旦考慮使用分布式鎖,又要考慮分布式鎖的載體的安全性,也即不管是用zookeeper或者redis,要考慮zookeeper或者redis的安全性(集群)。
這樣下去,問(wèn)題會(huì)變得非常復(fù)雜,純粹變?yōu)榻鉀Q問(wèn)題-->引入新的問(wèn)題-->解決問(wèn)題的死循環(huán)。
如果要保持一致,當(dāng)然雙寫也是一種選擇,不過(guò)通過(guò)雙寫來(lái)確保數(shù)據(jù)的絕對(duì)一致,不但會(huì)對(duì)整體效率產(chǎn)生負(fù)面的影響,實(shí)現(xiàn)也是比較困難的,暫時(shí)不討論這種方案。
如果是分布式鎖,任何寫入性操作,比如update,delete等,如下:
1,直接鎖定相關(guān)key值
2,依次操作緩存層和持久化層,同時(shí)做好每一層的回滾操作,一旦任何一步失敗,都要回滾
3,最終不管成功或者失敗,都釋放Key
分布式鎖這種方式的話,實(shí)現(xiàn)起來(lái),原代碼中業(yè)務(wù)侵入性較多,比較復(fù)雜
如果是使用隊(duì)列,將可能導(dǎo)致不一致性的訪問(wèn),隊(duì)列化執(zhí)行,其實(shí)這種方式,也是比分布式鎖更加重量級(jí)的,基本上會(huì)顛覆原始的邏輯實(shí)現(xiàn),一般很少采用。