什麼是快取 (Cache)?快取 (Cache) 的機制為何?
2023年2月5日
什麼是快取 (Cache)?
目的為了彌補 Database 在複雜業務下的不足,基本原理是將可重使用的資料存放到記憶體中,這樣可以避免每一次都去 Database 讀取,進而將地效能。而以 Memcache 為例,查詢可達到 TPS 50,000 以上。雖然說增加 Cache 可以減輕 Database 的壓力,但會讓系統變得複雜,因此若 Cache 沒有設計好,則有可能造成系統崩潰。
快取 (Cache) 的應用場景
- 需要經過複雜計算才能得到值:每一次從 MySQL 去 Count(*) 大量數據,則不管怎麼優化 MySQL 都無法解決這個問題。
- 讀多寫少的資料:在 Social media 上,寫的人少(insert)但讀的人多(select),即使 Database 有下 index,但每一個人都去 select 也會大幅降低效能。
快取 (Cache) 設計模式
Cache Aside
Read:優先從 Cache 讀,Cache miss 則從 Database 讀資料,並寫入 Cache,適合讀多的情境。
Write:把資料直接寫入 Database,成功後將 Cache 對應的 key 值設為失效。(不直接寫入 Cache 是為了避免併發問題。)
注意:還是會有併發問題,一個要讀、另一個要寫時,Cache 很有可能因此存在髒資料。
Read/Write Through
Cache 作為 Application 與 Database 之間的橋樑,適合寫少讀多的情境,機制如下:
Read through: 若 Cache hit 在 Cache 裡則直接回傳,否則從 Database 讀取並同時更新 Cache。
Write Through: 直接將資料寫入 Cache 以及 Database。
Write behind Cache
寫操作會直接寫入 Cache,而可依據不同策略決定寫回 Database 的時機,相比於 Write Through 的同步機制,這裡採取非同步的機制,適合寫入多的情境。但要注意若機器當機或 Thread 掛掉,則很有可能丟失資料。
快取 (Cache) 可能的問題
Cache penetration
Cache 並無作用,因此系統依舊還是要去找 Database ,具體可分為以下兩種情境
Database 本來就沒有這筆資料:照理來說這樣發生的請求量應該不大,但如果被惡意攻擊,有可能拖慢整個系統,解法可以是:
當搜尋的 Key 重複率較高時:把相對應個 Key 值給一個 default,這樣下次再被存取時就回傳空值。
當搜尋的 Key 重複率較低時:利用 Bloom filter(類似 hbase 判斷 key 否存在),若存在則去 Cache 或 Database 拿,反之則 return null。
緩存資料需耗費大量資源與時間:沒辦法把所有商品全部存到 Cache 裡,因此會需要分頁存,因此有可能在訪問時 Cache 會失效,進而 Cache 無法起到作用。
Cache avalanche
若 Key 全部都設同一個 Expire time,則當時間到會同時全部失效,此時會全部像 Database 索取資料,Database 會瞬間壓力過大,解決方法是利用一定區間的隨機值當來當作 Expire time。
Cache breakdown
Cache 失效後引起系統效能急遽下降的情況。例如當 key 值過期後,需要重新和 Database 拿資料,但是在拿資料的過程需要時間,若此時同時有大量訪問需求進來,全部都去 Database 拿資料就會造成問題,因此解法有兩種:
更新鎖:保證只有一個線程可以去更新緩存,其他線程則等待,不過當採分布式集群系統時,多個機器間也會產生緩存雪崩的問題,因此需要用到分布式鎖:Zookeeper
後台更新:由後台線程來更新緩存而非業務線程,具體會將 key 的期限設為永久,並且由後台線程定期清掃。但是當 cache 滿了時就會遇到問題,可能解法為:業務 thread 發現 cache 失效後,通過 message queue 發送一條消息通知後台 thread 更新 cache;或者後台 thread 依據對業務的了解,對於 Key 做定期清洗。
Hotspot cache
雖然 Cache 系統本身的性能比較高,但對於一些特別熱點的數據,如果大部分甚至所有的業務請求都命中同一份 Cache 數據,則這份數據所在的 Cache server 的壓力也很大,解決方法是,複製多份 Cache 副本到多個 Cache server ,減輕 Hotspot cache 導致的單台 Cache server 壓力。
注意:不同的 Cache 副本不要設置統一的過期時間,不然同時失效後可能引發 Cache avalanche。