關於快取穿透、快取併發、快取失效的解決方案
一、快取穿透
我們在專案中使用快取通常都是APP先檢查快取中是否存在,如果存在直接返回快取內容,如果不存在就直接查詢資料庫然後再快取查詢結果返回。這個時候如果我們查詢的某一個數據在快取中一直不存在,就會造成每一次請求都查詢DB,這樣快取就失去了意義,在流量大時,可能DB就掛掉了。
這個問題其實經常遇到,只是沒有引起足夠的重視,在我想來,如果碰到這樣的問題可以在封裝的快取SET和GET部分增加個步驟,如果查詢一個KEY不存在,就已這個KEY為字首設定一個標識KEY;以後再查詢該KEY的時候,先查詢標識KEY,如果標識KEY存在,就返回一個協定好的非FALSH或者NULL值,然後APP做相應的處理,這樣快取層就不會被穿透。當然這個驗證KEY的失效時間不能太長。
二、快取併發
有時候如果網站併發訪問高,一個快取如果失效,可能出現多個程序同時查詢DB,同時設定快取的情況,如果併發確實很大,這也可能造成DB壓力過大,還有快取頻繁更新的問題。
我現在的想法是再APP中對快取查詢加鎖,如果KEY不存在,就加鎖,然後查DB入快取,然後解鎖;其他程序如果發現有鎖就等待,然後等解鎖後返回資料或者進入DB查詢。
三、快取失效
引起這個問題的主要原因還是高併發的時候,平時我們設定一個快取的過期時間時,可能有一些會設定5分鐘啊,10分鐘這些;併發很高時可能會出在某一個時間同時生成了很多的快取,並且過期時間都一樣,這個時候就可能引發一當過期時間到後,這些快取同時失效,請求全部轉發到DB,DB可能會壓力過重。
前段時間我在網上也剛好看到了相關的文章,引用其中的一個簡單方案就時講快取失效時間分散開,比如我們可以在原有的失效時間基礎上增加一個隨機值,比如1-5分鐘隨機,這樣每一個快取的過期時間的重複率就會降低,就很難引發集體失效的事件。
第二、第三個問題其實差不多,主要就時第二個問題時針對同一個快取,第三個問題時針對很多快取