背景
本文結合一些自己理解土匀,講解cache miss等情況下如何保證緩存和db的一致性,下面的例子中緩存以redis為例
讀
先redis形用,redis沒有就讀db
寫
有幾種
1.先更新redis再更新db
2.先更新db再更新redis
3.先更新DB再刪除redis
4.先刪除redis再更新DB
5.延遲雙刪
6.延遲刪除等變種
各種寫場景與db redis一致性
1.先更新redis再更新db
按下面步驟會有問題,AB是兩個線程
A_update_redis
B_update_redis
B_update_db
A_update_db
最終db是a值但是redis是b值就轧,不一致
2.先更新db再更新redis
A_update_db
B_update_db
B_update_redis
A_update_redis
最終db是b值但是redis是a值
3.先更新DB再刪除redis
A_update_db
B_update_db
B_rm_redis
A_rm_redis
是不是不明白。想不出來怎么不一致了田度?
不是這樣的妒御,沒這么簡單,第二次rm_redis就會保證后面的redis和db是一致的
實際是下面這種形式
A_get_data
redis_cache_miss
A_get_db
B_update_db
B_rm_redis
(此時如果拿db是b值镇饺,但是redis沒有值)
A_update_redis
依賴于A_update_redis在B_update_db之后乎莉,極端情況
此時redis是old,db是new
4.先刪除redis再更新DB
A_rm_redis
B_get_data
B_redis_miss
B_get_db
B_update_redis
A_update_db
此時redis是old值奸笤,db是new值
5.延遲雙刪
即
rm_redis
update_db
sleep xxx ms
rm_redis
這樣叫做雙刪惋啃,最后一次sleep一段時間再rm_redis保證再次讀請求回溯打到db,用最新值寫redis
6.思考變種
上面的3和5情況可以直接變種监右,即
update_db
sleep xxx ms
rm_redis
解決了3中的極端情況(靠sleep解決)边灭,
并且減少5中第一次不必要的rm redis請求
當然,這個rm_redis還可以考慮異步化(提高吞吐)以及重試(避免異步處理失斀『小)绒瘦,這里不展示
總結
從db回源到redis,需要考慮上面這些極端情況的case
適用場景
當然這些極端情況本身要求同一個key是多寫的扣癣,這個根據業(yè)務需求來看是否需要惰帽,比如某些場景本身就是寫少讀多的
最終從網上看到的延遲雙刪變種為延遲刪除redis也是一種優(yōu)化
refer
https://my.oschina.net/LucasZhu/blog/1827267
https://blog.csdn.net/hjm4702192/article/details/80518922
https://shidonghua.work/2018/06/05/redis-DB-consistency/