今天回顧數(shù)據(jù)庫(kù)和緩存的一致性的場(chǎng)景有所感悟,因此有記:
不管是先刪除緩存再寫(xiě)入數(shù)據(jù)庫(kù)琼牧,還是先寫(xiě)入數(shù)據(jù)庫(kù)再刪除緩存砚哆,都有可能出現(xiàn)不一致的情況:
(1)先刪除緩存再寫(xiě)入數(shù)據(jù)庫(kù)
數(shù)據(jù)庫(kù)X = 1
線程A修改X=2:1、刪除了緩存厘灼,????????????????????????????????????????????????????????????????????????????????????????????????????3忿等、寫(xiě)入X=2
線程B查詢:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2栖忠、? 發(fā)現(xiàn)緩存無(wú)數(shù)據(jù),于是從數(shù)據(jù)庫(kù)查詢贸街,X=1庵寞,寫(xiě)入緩存
最終結(jié)果:緩存X=1,數(shù)據(jù)庫(kù)X=2
(2)先寫(xiě)入數(shù)據(jù)庫(kù)再刪除緩存
數(shù)據(jù)庫(kù)X = 1
線程A查詢:? ? 1薛匪、?發(fā)現(xiàn)緩存無(wú)數(shù)據(jù)捐川,于是從數(shù)據(jù)庫(kù)查詢,X=1逸尖,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????????????3古沥、寫(xiě)入緩存
線程B修改X=2:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2、更新數(shù)據(jù)庫(kù)X=2娇跟,刪除緩存
最終結(jié)果:緩存X=1岩齿,數(shù)據(jù)庫(kù)X=2
當(dāng)然(2)先寫(xiě)入數(shù)據(jù)庫(kù)再刪除緩存這個(gè)出現(xiàn)不一致的概率很低,因?yàn)橐鼻『谩暗挠凶x寫(xiě)并發(fā)苞俘,而且讀的線程比寫(xiě)的線程還慢盹沈,寫(xiě)線程本身就要加鎖。對(duì)比起來(lái)(1)先刪除緩存再寫(xiě)入數(shù)據(jù)吃谣,只要有讀寫(xiě)并發(fā)就很容易出現(xiàn)數(shù)據(jù)不一致的問(wèn)題乞封,已經(jīng)算是一個(gè)很好的解決方案。
但是還要考慮一個(gè)問(wèn)題岗憋,使用(2)的話肃晚,就是期間可能發(fā)生一些事故導(dǎo)致寫(xiě)入數(shù)據(jù)庫(kù)之后服務(wù)器無(wú)法正常執(zhí)行下去,重啟后會(huì)存在數(shù)據(jù)庫(kù)是2但是緩存還是1的問(wèn)題澜驮,但是如果是用(1)的話陷揪,先刪除緩存之后異常惋鸥,那么恢復(fù)之后的話緩存還是會(huì)去讀數(shù)據(jù)庫(kù)的1杂穷,好歹還是一致的,但是這導(dǎo)致了結(jié)果是舊值卦绣。這就是剩余的第二步執(zhí)行失敗的問(wèn)題了耐量。
所以在得出使用(1)是更好的方式的前提下,如何在(1)的第二步:刪除緩存 下功夫滤港?
1廊蜒、重試趴拧,使用第三方重試,這已經(jīng)算是比較受大家接受的方案了山叮,比如使用MQ刪除著榴。使用MQ不僅僅異步,還節(jié)省了工作線程的時(shí)間屁倔,畢竟重試多少次脑又?多久?總不能卡在這吧
2锐借、使用如canal等工具直接從數(shù)據(jù)庫(kù)问麸,如mysql中直接拉取對(duì)應(yīng)的binlog,根據(jù)這個(gè)binlog再對(duì)緩存進(jìn)行刪除
所以現(xiàn)在總結(jié)下來(lái)比較能讓人接受的總體方案大概為:
先寫(xiě)入數(shù)據(jù)庫(kù)钞翔,再刪除緩存
(一)(第二步的刪除緩存可以做優(yōu)化严卖,1、MQ執(zhí)行刪除 2布轿、canal讀取數(shù)據(jù)庫(kù)binlog再交給MQ執(zhí)行刪除)
其次還有主從延遲問(wèn)題
數(shù)據(jù)庫(kù)X=1
線程A執(zhí)行X=2:1哮笆、X=2寫(xiě)入數(shù)據(jù)庫(kù),刪除緩存? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 3汰扭、同步至從庫(kù)中
線程B查詢:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????2疟呐、查詢緩存為空,從庫(kù)中查詢到X=1东且,寫(xiě)入緩存
最終結(jié)果:緩存X=1启具,數(shù)據(jù)庫(kù)X=2
這個(gè)問(wèn)題其實(shí)解決方式和(一)一樣,都是執(zhí)行緩存刪除就能解決這個(gè)問(wèn)題珊泳,往后延遲刪除就肯定解決這個(gè)問(wèn)題
但是問(wèn)題就是鲁冯,不知道延遲多少才好,很難評(píng)估色查,這個(gè)需要參考生產(chǎn)環(huán)境才能做到的效果
先暫停一下薯演,回到我們的一致性問(wèn)題,那么我們現(xiàn)在做到這個(gè)步驟了秧了,發(fā)現(xiàn)了沒(méi)跨扮,其實(shí)我們的效果都是達(dá)到的是最終一致性
因?yàn)槲覀兊姆?wù)器一直在運(yùn)行,線程一直在工作验毡,有沒(méi)有必要做到強(qiáng)一致性呢衡创?只要查詢的時(shí)候就把所有修改操作都阻塞掉?不合理吧晶通。
但是還是有強(qiáng)一致性的方案如2pc璃氢,3pc等一致性協(xié)議。