瞭解快取擊穿
應對快取擊穿的解決方法 推薦閱讀
阿里一面:關於【快取穿透、快取擊穿、快取雪崩、熱點資料失效】問題的解決方案
快取熱點key問題(mutex key) 推薦閱讀
快取擊穿: 某一個熱點資料(key),在某一瞬間失效,導致大量的請求存取這一個熱點資料,擊穿快取,直接查詢資料庫。
解決方法:
設定熱點key永久不過期
定時更新熱點key快取資料
使用互斥鎖,分散式使用分散式鎖
更多方式參考:應對快取擊穿的解決方法
對於一個非常熱點的資料(key),直接設定快取永久不過期。
參照其他部落格的:「我們對主打商品都是早早的做好了準備,讓快取永不過期。即便某些商品自己發酵成了爆款,也是直接設為永不過期就好了。」
優點:方式簡單粗暴。
缺點:僅適用於基本不變化的資料。
參考 應對快取擊穿的解決方法
定時更新:
後臺定義一個job(定時任務)專門主動更新快取資料.比如,一個快取中的資料過期時間是30分鐘,那麼job每隔29分鐘定時重新整理資料(將從資料庫中查到的資料更新到快取中)。
不足:增加系統複雜度。比較適合那些 key 相對固定,cache 粒度較大的業務,key 比較分散的則不太適合,實現起來也比較複雜。
檢查更新:
將快取key的過期時間(絕對時間)一起儲存到快取中(可以拼接,可以新增新欄位,可以採用單獨的key儲存…不管用什麼方式,只要兩者建立好關聯關係就行).在每次執行get操作後,都將get出來的快取過期時間與當前系統時間做一個對比,如果快取過期時間-當前系統時間<=1分鐘(自定義的一個值),則主動更新快取.這樣就能保證快取中的資料始終是最新的(和方案一一樣,讓資料不過期.)
不足:假如在最後臨近的一分鐘沒有請求來獲取快取資料,有可能導致快取過期,並沒有重新載入。導致接下來的時間,大量請求到來,依然會出現快取擊穿。
使用互斥鎖就已經預設會出現,大量請求在同一時間,存取一個失效的熱點資料的情況。通過互斥鎖,只允許第一個執行緒獲得鎖,存取資料庫獲得資料再設定到快取中,其他執行緒等待,從更新的快取中獲得熱點資料。
單體應用可以使用(ReentrantLock)來實現互斥鎖。分散式系統可以使用分散式鎖(Redis setnx)(ZooKeeper) 等。
在閱讀一些部落格中,也提到了使用 hystrix 來實現資源隔離,還沒有研究,等研究了再實踐。
大道至簡,對於解決方法的選擇,不一定越複雜的越好,黑貓白貓逮到就是。