緩存,究竟是淘汰,還是修改?
允許cache miss的場景,不管是memcache還是redis,當被緩存的內(nèi)容變化時,是改修改緩存,還是淘汰緩存?這是今天將要討論的話題。
問:KV緩存都緩存了一些什么數(shù)據(jù)?
答:
- 樸素類型的數(shù)據(jù),例如:int
- 序列化后的對象,例如:User實體,本質(zhì)是binary
- 文本數(shù)據(jù),例如:json或者html
- ...
問:淘汰緩存中的這些數(shù)據(jù),修改緩存中的這些數(shù)據(jù),有什么差別?
答:
- 淘汰某個key,操作簡單,直接將key置為無效,但下一次該key的訪問會cache miss
- 修改某個key的內(nèi)容,邏輯相對復雜,但下一次該key的訪問仍會cache hit
可以看到,差異僅僅在于一次cache miss。
問:緩存中的value數(shù)據(jù)一般是怎么修改的?
答:
- 樸素類型的數(shù)據(jù),直接set修改后的值即可
- 序列化后的對象:一般需要先get數(shù)據(jù),反序列化成對象,修改其中的成員,再序列化為binary,再set數(shù)據(jù)
- json或者html數(shù)據(jù):一般也需要先get文本,parse成doom樹對象,修改相關(guān)元素,序列化為文本,再set數(shù)據(jù)
結(jié)論:對于對象類型,或者文本類型,修改緩存value的成本較高,一般選擇直接淘汰緩存。
問:對于樸素類型的數(shù)據(jù),究竟應該修改緩存,還是淘汰緩存?
答:仍然視情況而定。
案例1:
假設(shè),緩存里存了某一個用戶uid=123的余額是money=100元,業(yè)務(wù)場景是,購買了一個商品pid=456。
分析:如果修改緩存,可能需要:
- 去db查詢pid的價格是50元
- 去db查詢活動的折扣是8折(商品實際價格是40元)
- 去db查詢用戶的優(yōu)惠券是10元(用戶實際要支付30元)
- 從cache查詢get用戶的余額是100元
- 計算出剩余余額是100 - 30 = 70
- 到cache設(shè)置set用戶的余額是70
為了避免一次cache miss,需要額外增加若干次db與cache的交互,得不償失。
結(jié)論:此時,應該淘汰緩存,而不是修改緩存。
案例2:
假設(shè),緩存里存了某一個用戶uid=123的余額是money=100元,業(yè)務(wù)場景是,需要扣減30元。
分析:如果修改緩存,需要:
- 從cache查詢get用戶的余額是100元
- 計算出剩余余額是100 - 30 = 70
- 到cache設(shè)置set用戶的余額是70
為了避免一次cache miss,需要額外增加若干次cache的交互,以及業(yè)務(wù)的計算,得不償失。
結(jié)論:此時,應該淘汰緩存,而不是修改緩存。
案例3:
假設(shè),緩存里存了某一個用戶uid=123的余額是money=100元,業(yè)務(wù)場景是,余額要變?yōu)?0元。
分析:如果修改緩存,需要:
- 到cache設(shè)置set用戶的余額是70
修改緩存成本很低。
結(jié)論:此時,可以選擇修改緩存。當然,如果選擇淘汰緩存,只會額外增加一次cache miss,成本也不高。
總結(jié):
允許cache miss的KV緩存寫場景:
- 大部分情況,修改value成本會高于“增加一次cache miss”,因此應該淘汰緩存
- 如果還在糾結(jié),總是淘汰緩存,問題也不大
任何脫離分析的技術(shù)方案都是耍流氓。
【本文為51CTO專欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請聯(lián)系原作者】