當前位置:
首頁 > 知識 > 緩存實戰二三事

緩存實戰二三事

上次列舉了一些緩存相關的常見問題和解決思路,這些問題是在實際工作中可能會遇到的。很多系統在業務量不大時可能不會暴露出問題,但是遇到「高並發」就會產生很多問題,緩存也不例外。所以在選擇緩存策略和使用緩存之前,我們非常有必要結合當前的業務場景和需求去分析設計。一般我會從訪問頻率、讀寫比例、一致性要求等幾個維度去分析。

冷數據:

訪問頻度低,緩存的收益不明顯。

熱數據:

訪問頻度高,緩存收益一般明顯。

是否使用緩存,優先參考的是業務的訪問頻度和並發量,而不是執行速度。什麼意思呢?比如某個業務執行需要3s才能完成,我們覺得有點慢,但它本身使用頻度很低,也不存在什麼並發,那我們肯定會優先去給那些執行1s但是存在並發的業務加緩存。

讀多寫少:

適合緩存,收益明顯。

寫多讀少

不太適合緩存,收益不明顯,額外增加系統複雜度。

一致性要求低:

業務可以容忍(某段時間)出現不一致,可以最終一致。先天適合緩存,設計難度較低。

一致性要求高:

業務數據敏感,無法容忍不一致(或者可容忍時間非常短)。緩存設計難度相對較大。

面對的場景不同,緩存設計和處理策略也不同。我曾經見過一個系統的代碼,為了避免上面提到的「緩存並發」問題,直接在緩存幫助類中公共的get方法上加了lock,這顯然是不合理的。首先,並不是所有業務都會有「緩存穿透」的問題,其次,這種處理方式也太低級。

緩存並發導致的穿透問題如何解決

下面具體的聊聊我在實際工作中一般是如何應對解決「緩存並發穿透」問題的。

方案A(後台刷新):

在緩存過期之前,通過後台線程或者job主動更新緩存。例如,緩存的過期時間為30分鐘,而後台job則每隔29分鐘執行一次(job中查詢出最新的數據並寫入到緩存中)。

這種方案比較容易理解,但會增加系統複雜度。比較適合那些key相對固定、cache粒度較大的業務,key比較分散的則不太適合,實現起來也比較複雜。

方案B(檢查更新):

將緩存key的過期時間(絕對時間)也一起保存到緩存中(可以拼接,也可以加新欄位,也可以採用單獨的key保存,反正需要兩者建立好關聯關係)。在每次執行get操作後,都將get出來的緩存過期時間與當前系統時間做一個對比,如果發現緩存過期時間-當前系統時間

這種方案在特殊情況下也會有問題。假設緩存過期時間是11:30分,而11:29到11:30這1分鐘時間裡恰好沒有get請求過來,恰好請求都在11:30分的時候並發過來,那就悲劇了。這種情況比較極端,但並不是沒有可能。因為「高並發」也可能是階段性在某個時間點爆發。

方案C(分級緩存):

分級緩存。採用L1和L2緩存方式,L1緩存失效時間短,L2緩存失效時間長。請求優先從L1緩存獲取數據,如果L1緩存未命中則加鎖,只有1個線程獲取到鎖,改線程從資料庫中讀取,再將數據set到L1緩存和L2緩存中,而其他線程依舊從L2緩存獲取數據並返回。

這種方式,主要是通過避免緩存同時失效並結合鎖機制實現。所以,當數據更新時,只能淘汰L1緩存,不能同時將L1和L2中的緩存同時淘汰。L2緩存中可能會存在臟數據,需要業務能夠容忍這種短時間的不一致。而且,這種方案可能會造成額外的緩存空間浪費。

方案D(互斥鎖):

加鎖等待。採用互斥鎖的方式。

注意,不能直接在緩存載入邏輯判斷時直接採用synchronize。下面列出幾種常見做法:

方法1:

這種方式,確實能夠防止緩存失效時並發打到資料庫,但緩存沒有失效的時候呢?也需要排隊獲取鎖然後去獲取數據,豈不是大大降低了系統的吞吐量。

還有另外一種寫法:

方法2:

這種方式,當緩存命中的時候,系統的吞吐量是不會受影響的。但是,緩存失效的時候,請求還是會打到資料庫中,只不過不是並發的,而是阻塞進行的,無疑會犧牲用戶體驗,並給資料庫帶來額外的壓力。

方法3:

這種做法呢。似乎避免了前面那2種問題,但似乎還是不太完美。因為執行雙重檢查的那裡,雖然是避免了請求打到資料庫,但是命中緩存的過程依舊是排隊進行的。

例如:當緩存失效時,有30個請求並發讀庫。使用同步加雙重檢查機制,可以讓1個線程先讀庫然後寫緩存了,剩下的29個線程命中緩存。但是,那29個線程是串列排隊的在讀緩存,效率方面肯定有影響。

方法4:

使用互斥鎖的方式來實現,可以有效避免前面幾種問題。為了方便演示和測試,就直接使用的Java中的ReentranLock。

在實際分散式場景中,可以使用redis、tair、zookeeper等提供的分散式鎖來實現,感興趣的朋友自行查閱相關資料,這裡不展開。

新書推薦:《深入分散式緩存》

馬雲老哥忒給力了,

每天加上普通紅包+專屬紅包1-99元隨便領。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 PHP技術大全 的精彩文章:

PHP女架構師打怪升級

TAG:PHP技術大全 |