在設計和開發高可用性系統時,快取是一個非常重要的考量。快取一些經常存取的資料很有用,這樣可以快速存取,而且快取還可以保護下游系統(如資料庫)免於過於頻繁的存取。
為了在大型系統中提供更好的快取設計,可能需要先考慮一些問題。在這篇文章中,我們將討論一些經常被討論的快取問題和緩解計畫。
快取穿透
快取穿透是指要搜尋的資料在資料庫中不存在,且返回的空結果集也沒有被快取,因此每次搜尋該鍵都會最終命中資料庫的情況。如果駭客試圖透過發起大量使用此類鍵的搜尋來發起攻擊,底層資料庫層將會被過於頻繁地命中,並可能最終被擊垮。
在這種情況下,有一些緩解計畫。
- 如果資料庫中沒有該鍵的資料,只需返回一個空的結果並將其快取一段短時間(不要設定過長的到期時間)
- 使用 Bloom filter。Bloom filter 類似於 hbase set,可用於檢查資料集中是否存在某個鍵。如果該鍵存在,則轉到快取層或資料庫層;如果該鍵在資料集中不存在,則直接返回。
如果搜尋的鍵具有高重複率,則可以採用第一種解決方案。否則,如果搜尋的鍵具有低重複率且搜尋的鍵太多,則可以採用第二種解決方案來首先過濾掉大多數鍵。
快取擊穿
快取擊穿是指快取的資料過期,同時對過期的資料進行大量搜尋,這會突然導致搜尋直接命中資料庫,並大幅增加資料庫層的負載的情況。
這會在高並發環境中發生。通常在這種情況下,需要對搜尋的鍵進行鎖定,以便當某些執行緒嘗試搜尋該鍵並更新快取時,其他執行緒需要等待。在快取更新且鎖定釋放後,其他執行緒將能夠讀取新快取的資料。
另一種可行的方法是透過工作執行緒非同步更新快取的資料,以便熱門資料永遠不會過期。
快取雪崩
快取雪崩是指大量快取的資料同時過期,或者快取服務關閉,突然之間所有對這些資料的搜尋都會命中資料庫,導致資料庫層的高負載並影響效能的情況。
為了緩解這個問題,可以採用一些方法。
- 使用叢集來確保在任何時間點都有一些快取伺服器執行個體在服務中。如果使用 Redis,則可以擁有 redis 叢集。
- 可以配置一些其他方法,如 hystrix 斷路器和速率限制,以便底層系統仍然可以服務流量並避免高負載
- 可以調整不同鍵的到期時間,以便它們不會同時過期。
所有緩解方法都需要根據實際用例和系統設計要求來實施。