选择语言
durumis AI 总结的文章
- 快取是一種通過儲存頻繁讀取、寫入頻率低的數據來提高服務效率的技術。可以使用 APM(例如 DataDog)分析 RDB 的查詢呼叫記錄來選擇快取目標。
- 本地快取將快取數據儲存在應用程式伺服器的記憶體中,速度很快,但可能會出現實例之間快取同步問題。全局快取使用 Redis 等獨立伺服器儲存快取數據,可以實現實例之間共享,但由於網路流量,速度可能會變慢。
- 為了更新快取,會使用 TTL(生存時間)。如果讀取/寫入發生在同一台伺服器上,通常會設定以小時為單位的 TTL,如果發生在多台伺服器上,則通常會設定以秒或分鐘為單位的 TTL。
您好!我是 Jayeon。
今天我想跟大家說明設定快取的標準。這篇文章是我在實際工作中遇到的問題,所以僅供參考,哈哈!
什麼是快取?
快取是指將之後可能會被請求的結果預先儲存起來,以便快速提供服務。也就是說,預先儲存結果,然後當收到請求時, 直接從快取中讀取結果,而不用去訪問資料庫或API。快取的出現是基於帕累托法則。
帕累托法則是指80%的結果是由20%的原因造成的,您可以參考下面的圖片!
也就是說,快取不必儲存所有結果,只需要儲存服務中常用的20%,這樣可以提高整體效率。
應該快取哪些數據?
根據帕累托法則,我們不應該快取任何數據,而應該快取必要的數據。那麼,應該快取哪些數據呢?
頻繁讀取但很少寫入的數據
很多人會說,"應該快取頻繁讀取但很少寫入的數據。",但"頻繁讀取"和"很少寫入"的標準都很模糊。
所以我會按照以下步驟調查要快取的數據。
- 通過APM(如DataDog)查看RDB中查詢呼叫記錄的前5名。
- 在其中尋找查詢查詢,並確認查詢來自哪個表格。
- 查看該表格的更新查詢被呼叫了多少次。
通過這些步驟,我們就可以查看哪些數據查詢頻繁,但更新查詢很少。我在實際工作中遇到的一個表格,查詢查詢每天 發生174萬次,而更新查詢最多只有500次。這很明顯是一個適合快取的條件,哈哈!
對最新更新敏感的數據
對最新更新敏感的數據意味著RDB和快取之間的差異時間要很短。例如,與支付相關的資訊對最新更新非常敏感, 即使符合上述快取條件,也需要慎重考慮是否要應用快取。
我需要為滿足上述兩種特性的與支付相關的表格應用快取。因此,我並沒有對所有使用該支付相關表格的邏輯應用快取, 而是選擇在實際上不會發生支付的相對安全的邏輯中部分應用快取。
本地快取 vs 全局快取
現在,我們已經確定了要快取的數據和快取的範圍。接下來,我們需要考慮將快取數據儲存在哪裡。一般來說,可以儲存 在本地記憶體中,也可以儲存在Redis等獨立的伺服器中。
本地快取
本地快取是指將快取數據儲存在應用程式伺服器的記憶體中,通常使用Guava快取或Caffeine快取。
優點
- 在執行應用程式邏輯時,可以直接從同一台伺服器的記憶體中查詢快取,因此速度很快。
- 易於實現。
缺點
- 如果有多個實例,就會出現很多問題。
- 一個實例中修改的快取無法傳播到其他實例。當然,也有一些本地快取庫可以將修改傳播到其他實例。
- 每個實例都會儲存快取,因此當啟動新的實例時,需要重新建立快取。這會導致大量的快取遺漏, 無法承受流量,導致實例崩潰。
全局快取
全局快取是指將快取數據儲存在獨立的伺服器中,例如Redis。
優點
- 實例之間共用快取,因此即使一個實例修改了快取,所有實例都可以獲得相同的快取值。
- 即使啟動新的實例,也可以直接訪問現有的快取儲存庫,而不需要重新建立快取。
缺點
- 需要經過網路傳輸,因此速度比本地快取慢。
- 需要獨立的快取伺服器,因此會產生基礎設施管理成本。
- 基礎設施管理成本?→ 伺服器費用、基礎設施設定和維護所花費的時間、故障應對措施等
我選擇了什麼?
目前公司應用程式伺服器採用多實例架構,但我選擇了本地快取。
主要原因有三個:
- 儲存在RDB中的要快取的數據約為4萬條,即使全部載入到記憶體中,也只有4MB以下。
- 需要提高與支付相關數據的查詢性能。
- 雖然已經存在Redis,但將新的快取儲存在Redis中會產生基礎設施成本。
如何更新快取?
如果應用程式伺服器有多個,並且在這些伺服器上應用本地快取,那麼每個應用程式伺服器上儲存的快取值可能不同。 例如,A伺服器上儲存的快取數據為“1”,而B伺服器上儲存的快取數據可能因B伺服器上的修改而變為“2”。 在这种情况下,如果用户向负载均衡器发送请求,A服务器和B服务器将收到不同的值。
因此,需要將每個實例的快取自動清除,並從RDB中查詢數據。這時,通常會使用TTL。
TTL應該設定為多少?
TTL是Time To Live的縮寫,是指設定快取數據在一段時間後自動清除的設定。例如,如果將TTL設定為5秒, 那麼快取數據将在5秒後自动清除。之後,如果發生快取遺漏,就會從RDB中查詢數據並儲存起來。
那麼,TTL應該設定為多少呢?
讀寫操作在一個快取伺服器上發生
如果讀寫操作在一個全局快取伺服器(例如Redis)上發生,或是在一個應用本地快取伺服器上發生,那麼將TTL的值 設置為時間單位以上是沒有問題的。因為在寫入時會修改現有的快取,而從該快取中獲取数据的伺服器始終會看到 最新的數據。
在这种情况下,可以不设置TTL,而是当快取伺服器滿了時,使用LRU演算法自動逐漸清空快取。
讀寫操作在多個快取伺服器上發生
如果讀寫操作在多個全局快取伺服器上發生,或是在多個應用本地快取伺服器上發生,那麼TTL最好設置為秒到分鐘 的單位。這是因為有可能讀取到未反映修改數據的舊數據,這些數據儲存在其他快取伺服器中。
在这种情况下,TTL的设置取决于多种情况。如果最新更新很重要,并且数据变更的可能性很高,那么TTL应该设置 得更短。如果最新更新不太重要,并且数据变更的可能性很低,那么TTL可以设置得更长一些。
我如何设置TTL?
我需要快取的數據是與支付相關的數據,雖然沒有將快取應用於實際發生支付的嚴格邏輯,但由于支付的特性, 最新更新非常重要。然而,更新的可能性很低,所以我將TTL設定為5秒,確保安全。
結論
总结一下,我选择的快取方式如下:
- 與支付相關的數據
- 查詢非常頻繁,但修改很少。
- 僅對實際上沒有發生支付,但會發生查詢的邏輯應用快取。
- 應用本地快取,TTL設定為5秒。
下一步,我會對實際應用的快取方式進行性能測試。目前還沒有確定如何進行性能測試,之後我會在後續文章中 說明!