大前提
- 如果要求強(qiáng)一致性,就不要使用redis,使用redis代表可以接受最終一致性
- 使用redis作為緩存,必須設(shè)置過期時(shí)間踪栋,原因: 即使程序有問題,不能保證redis的最終一致性姻报,key也會(huì)自己失效
保證redis與mysql數(shù)據(jù)最終一致性己英,有以下幾種方案
方案一
先更新redis,再更新mysql
流程圖
最后mysql是請求1的數(shù)據(jù)吴旋,redis是請求2的數(shù)據(jù)损肛,不能保證最終一致性
方案二
先更新mysql厢破,再更新redis
流程圖
最后mysql是請求2的數(shù)據(jù),redis是請求1的數(shù)據(jù)治拿,不能保證最終一致性
方案三
先刪redis摩泪,再更新mysql
流程圖
最后mysql是新數(shù)據(jù),redis是舊數(shù)據(jù)劫谅,不能保證最終一致性
方案四
先更新mysql见坑,再刪redis
流程圖
最后mysql是新數(shù)據(jù),redis是舊數(shù)據(jù)
方案五
延遲刪除: 先更新mysql捏检,然后sleep一段時(shí)間荞驴,再刪除redis
流程圖
sleep時(shí)間,由業(yè)務(wù)側(cè)決定贯城,最好是大于查詢接口的耗時(shí)熊楼。
方案六
方案五的問題是: 更新mysql后,刪除redis之前能犯,查詢請求從redis查到的是舊數(shù)據(jù)鲫骗,雖然可以保證最終一致性,但是查到舊數(shù)據(jù)的時(shí)間較長踩晶。
基于方案五的問題执泰,方案六提出了延遲雙刪: 先刪redis,然后更新mysql渡蜻,然后sleep一段時(shí)間术吝,再刪除redis。
本方案可以讓用戶更早查詢到新數(shù)據(jù)茸苇。
方案六看起來是所有方案中最優(yōu)的顿苇,但其實(shí)還是有問題,比如下面的情況(出現(xiàn)概率極低)税弃,如果確實(shí)發(fā)生了這種情況,只能等key到達(dá)過期時(shí)間自己失效凑队,或者引入mq等中間件對刪除redis失敗做重試则果。
最后,友情提示一下漩氨,這個(gè)問題是面試高頻題西壮,但是面試沒法畫圖,很難描述清楚各種場景叫惊,可以用下面的表達(dá)方式
請求1: 更新redis--------------------------------------更新mysql
請求2: -------------更新redis--------------更新mysql
最后redis是請求2的數(shù)據(jù)款青,mysql是請求1的數(shù)據(jù)