容許cache miss的場景,無論是memcache仍是redis,當被緩存的內容變化時,是修改緩存,仍是淘汰緩存?這是今天將要討論的話題。html
問:KV緩存都緩存了一些什麼數據?
答:
(1)樸素類型的數據,例如:int
(2)序列化後的對象,例如:User實體,本質是binary
(3)文本數據,例如:json或者html
(4)...redis
問:淘汰緩存中的這些數據,修改緩存中的這些數據,有什麼差異?
答:
(1)淘汰某個key,操做簡單,直接將key置爲無效,但下一次該key的訪問會cache miss
(2)修改某個key的內容,邏輯相對複雜,但下一次該key的訪問仍會cache hitjson
能夠看到,差別僅僅在於一次cache miss。緩存
問:緩存中的value數據通常是怎麼修改的?
答:
(1)樸素類型的數據,直接set修改後的值便可
(2)序列化後的對象:通常須要先get數據,反序列化成對象,修改其中的成員,再序列化爲binary,再set數據
(3)json或者html數據:通常也須要先get文本,parse成doom樹對象,修改相關元素,序列化爲文本,再set數據ui
結論:對於對象類型,或者文本類型,修改緩存value的成本較高,通常選擇直接淘汰緩存。spa
問:對於樸素類型的數據,究竟應該修改緩存,仍是淘汰緩存?
答:仍然視狀況而定。htm
案例1:對象
假設,緩存裏存了某一個用戶uid=123的餘額是money=100元,業務場景是,購買了一個商品pid=456。get
分析:若是修改緩存,可能須要:
(1)去db查詢pid的價格是50元
(2)去db查詢活動的折扣是8折(商品實際價格是40元)
(3)去db查詢用戶的優惠券是10元(用戶實際要支付30元)
(4)從cache查詢get用戶的餘額是100元
(5)計算出剩餘餘額是100 - 30 = 70
(6)到cache設置set用戶的餘額是70
爲了不一次cache miss,須要額外增長若干次db與cache的交互,得不償失。it
結論:此時,應該淘汰緩存,而不是修改緩存。
案例2:
假設,緩存裏存了某一個用戶uid=123的餘額是money=100元,業務場景是,須要扣減30元。
分析:若是修改緩存,須要:
(1)從cache查詢get用戶的餘額是100元
(2)計算出剩餘餘額是100 - 30 = 70
(3)到cache設置set用戶的餘額是70
爲了不一次cache miss,須要額外增長若干次cache的交互,以及業務的計算,得不償失。
結論:此時,應該淘汰緩存,而不是修改緩存。
案例3:
假設,緩存裏存了某一個用戶uid=123的餘額是money=100元,業務場景是,餘額要變爲70元。
分析:若是修改緩存,須要:
(1)到cache設置set用戶的餘額是70
修改緩存成本很低。
結論:此時,能夠選擇修改緩存。固然,若是選擇淘汰緩存,只會額外增長一次cache miss,成本也不高。
總結:
容許cache miss的KV緩存寫場景:
大部分狀況,修改value成本會高於「增長一次cache miss」,所以應該淘汰緩存
若是還在糾結,老是淘汰緩存,問題也不大