【58沈劍 架構師之路】快取,究竟是淘汰,還是修改?
允許cache miss的場景,不管是memcache還是redis,當被快取的內容變化時,是修改快取,還是淘汰快取?這是今天將要討論的話題。
問:KV快取都快取了一些什麼資料?
答:
(1)樸素型別的資料,例如:int
(2)序列化後的物件,例如:User實體,本質是binary
(3)文字資料,例如:json或者html
(4)...
問:淘汰快取中的這些資料,修改快取中的這些資料,有什麼差別?
答:
(1)淘汰某個key,操作簡單,直接將key置為無效,但下一次該key的訪問會cache miss
(2)修改某個key的內容,邏輯相對複雜,但下一次該key的訪問仍會cache hit
可以看到,差異僅僅在於一次cache miss。
問:快取中的value資料一般是怎麼修改的?
答:
(1)樸素型別的資料,直接set修改後的值即可
(2)序列化後的物件:一般需要先get資料,反序列化成物件,修改其中的成員,再序列化為binary,再set資料
(3)json或者html資料:一般也需要先get文字,parse成doom樹物件,修改相關元素,序列化為文字,再set資料
結論:對於物件型別,或者文字型別,修改快取value的成本較高,一般選擇直接淘汰快取。
問:對於樸素型別的資料,究竟應該修改快取,還是淘汰快取?
答:仍然視情況而定。
案例1:
假設,快取裡存了某一個使用者uid=123的餘額是money=100元,業務場景是,購買了一個商品pid=456。
分析:如果修改快取,可能需要:
(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的互動,得不償失。
結論:此時,應該淘汰快取,而不是修改快取。
案例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”,因此應該淘汰快取
-
如果還在糾結,總是淘汰快取,問題也不大