為什么會數(shù)據(jù)不一致
寫流程:
- 先淘汰cache
- 再寫入數(shù)據(jù)庫
讀流程:
- 先讀cache坞靶,如果數(shù)據(jù)命中則返回
- 如果數(shù)據(jù)未命中則讀數(shù)據(jù)庫
- 將數(shù)據(jù)庫中讀取出來的數(shù)據(jù)入緩存
但是會發(fā)生以下情況導(dǎo)致不一致:
- 發(fā)生了寫請求A谆扎,A的第一步淘汰了cache
- A的第二步寫數(shù)據(jù)庫汗销,發(fā)出修改請求
- 發(fā)生了讀請求B连霉,B的第一步讀取cache勇皇,發(fā)現(xiàn)cache中是空的
- B的第二步讀取數(shù)據(jù)庫,如果讀操作B發(fā)生在寫操作A之前谍憔,就會讀出了一個臟數(shù)據(jù)放入cache
優(yōu)化解決方案
以項目中的商品庫存為例匪蝙,如果數(shù)據(jù)庫中產(chǎn)品的庫存是100主籍,那么查詢到的庫存是100,然后插入緩存逛球,插入完緩存后千元,原來那個更新數(shù)據(jù)庫的線程把數(shù)據(jù)庫更新為了99,導(dǎo)致數(shù)據(jù)庫與緩存不一致的情況
針對上面的場景:創(chuàng)建一個隊列需忿,當(dāng)有寫請求時诅炉,先把它丟到隊列里去,當(dāng)寫請求完后在從隊列里去除屋厘。如果在寫的過程中,遇到了上述場景月而,先去緩存里看下有沒有數(shù)據(jù)汗洒,如果沒有,再去看看隊列中看看相應(yīng)的寫請求沒有完成父款,如果沒有完成就把查詢請求放到相同的隊列中溢谤,直到寫請求完成后才執(zhí)行查詢操作
補充
對于緩存和數(shù)據(jù)庫不一致的情況,可以先清除緩存憨攒,第一個數(shù)據(jù)庫查詢請求到達數(shù)據(jù)庫世杀,將讀取到的值更新到緩存,這樣緩存與數(shù)據(jù)庫就是一致的