高併發系統設計十一-緩存的使用一(如何選擇緩存的讀寫策略)

緩存的使用一-如何選擇緩存的讀寫策略

緩存在實際項目中的使用,選擇緩存策略時需要考慮不同的因素:

  • 緩存中是否有可能被寫入髒數據
  • 策略的讀寫性能如何
  • 是否存在緩存命中率下降的情況

1、Cache Aside(旁路緩存)策略

更新數據時不更新緩存,而是刪除緩存中的數據,在讀取數據時,發現緩存中沒有了數據之後,再從數據庫中讀取數據,更新到緩存中。

這個策略是以數據中的數據爲準,緩存中的數據是按需加載的,可以分爲讀策略和寫策略:

  • 讀策略的步驟
    • 從緩存中讀取數據
    • 如果緩存命中,則直接返回數據
    • 如果緩存中不命中,則從數據庫中查詢數據
    • 查詢到數據後,將數據寫入到緩存中,並返回給用戶
  • 寫策略
    • 更新數據庫中的記錄
    • 刪除緩存記錄

1.1、場景分析

1、在寫策略中是否可以先刪除緩存,後更新數據呢?這樣是不行的,這樣可能會出現緩存數據不一致的問題:

假設某個用戶的年齡爲20,請求A更改用戶年齡爲21,所有它會刪除緩存中的內容,這個時候,請求B要讀這個用戶的年齡,它查詢緩存發現未命中後,會從數據庫中讀取到年齡爲20,並寫入到緩存中,但是請求A繼續更改數據庫,將用戶的年齡更新爲了21,就造成了緩存和數據庫的不一致性。

2、新註冊一個用戶,是否也要按照這個策略來處理呢?

當新註冊一個用戶,按照這個更新策略,寫數據庫,然後清理緩存(這時候緩存中也麼有數據可清理)。可當我註冊用戶後立即讀取用戶信息,並且數據庫主從分離時,會出現因爲主從延時而讀不到用戶信息的情況。

解決這個問題,在插入新數據到數據庫之後,直接寫入緩存中,這樣後續的讀請求就會從緩存中讀取數據了,並且因爲是新註冊的用戶,所有不會存在併發更新用戶信息的情況。

1.2、Cache Aside 存在的問題

就是寫入比較頻繁,緩存中的數據會被頻繁地清理,對緩存的命中率有一些影響。

如果業務對緩存的命中率有要求的話,可以考慮兩種解決辦法:

  • 在更新數據時也更新緩存,只是在更新緩存前先加一個分佈式鎖,在同一時間只允許一個線程更新緩存,就不會產生併發問題了,但是這樣的話會對寫入性能有一定的影響
  • 更新數據庫時也更新緩存,只是給緩存加一個較短的過期時間,這樣即使緩存出現緩存不一致的情況,緩存的數據也會很快的過期,對業務影響也是比較小的

2、Read/Write Through(讀穿 / 寫穿)策略

用戶只與緩存打交道,由緩存和數據庫通信,寫入或者讀取數據。這就好比你在彙報工作的時候只對你的直接上級彙報,再由你的直接上級彙報給他的上級,你是不能越級彙報的。

2.1、Write Through 的策略

先查詢要寫入的數據在緩存中是否已經存在,如果已經存在,則更新緩存中的數據,並且由緩存組件同步更新到數據庫中,如果緩存中數據不存在,我們把這種情況叫做“Write Miss(寫失效)”,然後 使用“No-write allocate(不按寫分配)”,做法是不寫入緩存中,而是直接更新到數據庫中

一般來說,我們可以選擇兩種“Write Miss”方式:一個是“Write Allocate(按寫分配)”,做法是寫入緩存相應位置,再由緩存組件同步更新到數據庫中;另一個是“No-write allocate(不按寫分配)”,做法是不寫入緩存中,而是直接更新到數據庫中。

2.2、Read Through 策略

先查詢緩存中數據是否存在,如果存在則直接返回,如果不存在,則由緩存組件負責從數據庫中同步加載數據

這種策略方式使用較少

  • Memcached、Redis 都不提供寫入數據庫
  • Write Through 策略中寫數據庫是同步的,這個對性能會有較大的影響。

3、Write Back(寫回)策略

寫入數據時只寫入緩存,並且把緩存塊兒標記爲“髒”的。而髒塊兒只有被再次使用時纔會將其中的數據寫入到後端存儲中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章