一、引言
緩存技術作為高并發架構設計的基石之一,通過數據暫存和快速訪問機制,在提升系統性能、降低后端負載方面發揮著不可替代的作用。優秀的緩存設計能夠將系統吞吐量提升數個數量級,將響應時間從秒級降至毫秒級,甚至成為系統能否平穩度過流量高峰的決定性因素。從緩存策略的選擇到一致性保障,從多級緩存架構到分布式緩存集群,從緩存穿透防護到熱點數據發現,每個環節都需要架構師深入理解業務特性并做出精準決策。不當的緩存設計不僅無法提升性能,反而可能導致系統穩定性下降甚至災難性故障。本文將系統性地探討高并發架構中的緩存設計方法論,包括但不限于:緩存的核心原理與價值體現、典型緩存模式與適用場景、分布式緩存的實現策略、緩存一致性的解決方案、緩存異常情況的應對機制,以及緩存技術的最新發展趨勢。
二、高并發
2.1 高并發的定義
高并發是指系統或應用程序在同一時間段內接收到大量并發請求的能力。具體來說,高并發環境下系統需要能夠同時處理大量的請求,而不會出現性能問題或響應延遲。
2.2?高并發的特點
- 大量請求:高并發場景下,系統需要同時處理大量的請求,這些請求可能來自于不同的用戶或客戶端。
- 同時訪問:這些請求幾乎同時到達系統,需要在短時間內進行處理和響應。
- 資源競爭:由于大量請求同時到達,系統的資源(如CPU、內存、網絡帶寬等)可能會面臨競爭和爭奪。
- 響應時間要求高:高并發場景通常對系統的響應速度有較高的要求,用戶期望能夠快速獲取響應結果。
2.3?高并發的影響
- 系統性能的下降和延遲增加
- 資源競爭和資源耗盡
- 系統穩定性和可用性的挑戰
2.4 高并發應對策略
- 緩存:緩解系統負載壓力,提高系統響應速度
- 限流:控制并發訪問量,保護系統免受過載影響
- 降級:保證核心功能的穩定性,舍棄非關鍵業務或簡化處理
三、緩存
緩存的工作原理是先從緩存中獲取數據,如果有數據則直接返回給用戶,如果沒有數據則從慢速設備上讀取實際數據并且將數據放入緩存。
接下來我們來看看從前端到后端常用的緩存技術。
3.1?瀏覽器緩存
3.1.1 概述
瀏覽器緩存是指將網頁中的資源(如HTML、CSS、JavaScript、圖像等)存儲在用戶的瀏覽器內部,以便在后續請求同一資源時可以直接從本地緩存中獲取,而無需再次從服務器下載。
3.1.2 適用場景
瀏覽器緩存適用于那些靜態內容變化較少的網頁和靜態資源,可以顯著提升網站性能和用戶體驗,并減少服務器的負載。
3.1.3 常見用法
使用瀏覽器緩存可以通過設置響應頭中的Expires和Cache-Control字段來控制緩存的行為。
- 使用Expires字段:Expires字段指定了緩存的過期時間,是一個具體的日期和時間。服務器可以在響應頭中添加Expires字段,告訴瀏覽器在該時間之前可以直接從緩存中獲取資源,而無需再向服務器發起請求。例如:Expires: Mon, 31 Dec 2022 23:59:59 GMT。
- 使用Cache-Control字段:Cache-Control字段提供了更靈活的緩存控制選項。可以通過設置max-age指令來指定緩存的最大有效時間,單位是秒。例如:Cache-Control: max-age=3600 表示資源可以在1小時內直接從緩存中獲取。還可以使用其他指令,如no-cache表示緩存但不使用緩存、no-store表示禁止緩存等。
3.2?客戶端緩存
3.2.1 概述
客戶端緩存是將數據存儲在瀏覽器中,以提高訪問速度和減少服務器請求。
3.2.2?適用場景
在大促期間,為了防止服務端承受瞬間的高流量壓力,可以提前將一些素材(如js/css/image等)下發到客戶端進行緩存,避免在大促期間再次請求這些素材。此外,還可以將一些兜底數據或樣式文件存放在客戶端緩存中,以確保在服務端異常或網絡異常的情況下,保持app的正常運行。
3.3?CDN緩存
3.3.1 概述
CDN(Content Delivery Network)是建立在承載網之上的分布式網絡,由分布在不同區域的邊緣節點服務器組成。
CDN緩存通常用于存放靜態頁面數據、活動頁面、圖片等數據。它有兩種緩存機制:推送機制(將數據主動推送到CDN節點)和拉取機制(首次訪問時從源服務器獲取數據并存儲在CDN節點)。
3.3.2?適用場景
CDN緩存可以提高網站訪問速度,適用于網站訪問量大、訪問速度慢、數據變化不頻繁的場景。
3.3.3?常用工具以及用法
常見的CDN緩存工具包括Cloudflare、Akamai、Fastly和AWS CloudFront等。這些工具提供了全球分布的CDN網絡,以加速內容傳輸和提升性能。它們提供了控制臺和API,用于配置CDN緩存規則、管理緩存內容、刷新和更新緩存等。
3.4?反向代理緩存
3.4.1?概述
反向代理緩存是指在反向代理服務器上對請求的響應進行緩存,以提高服務的性能和用戶體驗。它將經常請求的靜態內容緩存在代理服務器上,當有用戶請求同樣的內容時,代理服務器會直接返回緩存的響應,而無需再次向源服務器請求。
3.4.2?適用場景
適用于訪問外部服務速度比較慢,但是數據變化不頻繁的場景。
3.4.3?常用工具以及用法
- Nginx:一款高性能的反向代理服務器,支持反向代理緩存功能,可通過配置文件進行緩存策略的設置。Nginx代理層緩存主要以Http模塊與proxy_cacahe模塊進行配置即可。
- Varnish:一個專門用于反向代理緩存的開源軟件,可以高效地緩存并提供快速的響應。
- Squid:一款功能強大的緩存代理服務器,支持反向代理緩存和正向代理緩存。
3.5 本地緩存
3.5.1?概述
本地緩存是將數據或資源存儲在客戶端的存儲介質中,如硬盤、內存或數據庫。它可以是臨時的,只在應用程序運行期間有效,或者可以是持久的,即在不同的應用程序會話中保持有效。
3.5.2?適用場景
本地緩存適用于頻繁訪問數據、離線訪問、減少帶寬消耗和提升用戶體驗的場景。
常用工具以及用法
一般分為磁盤緩存、CPU緩存、應用緩存
- 磁盤緩存:存儲在硬盤等永久性存儲介質上,用于加速數據的讀取和訪問。
- CPU緩存:位于處理器內部的高速存儲器,用于暫時存儲頻繁訪問的數據或指令,提高計算機的性能。
- 應用緩存:存儲在內存中的應用程序數據或資源,用于提高應用程序的響應速度和用戶體驗。用Java服務來舉例,又分為 堆內緩存 與 堆外緩存 。
3.6?分布式緩存
3.6.1?概述
分布式緩存是將緩存數據分散存儲在多臺服務器上的緩存解決方案。
3.6.2?適用場景
高并發讀取、數據共享和協同處理、提供彈性和可擴展性、降低后端請求次數等場景。
3.6.3?常用工具以及用法
- Redis:Redis是一種高性能的鍵值存儲系統,支持豐富的數據類型和靈活的緩存策略。可以使用Redis搭建分布式緩存集群,利用其快速的讀寫能力和一致性哈希算法實現數據分片和負載均衡。
- Memcached:Memcached是一種簡單而快速的分布式內存對象緩存系統,用于減輕數據庫負載和加速動態Web應用程序。它采用分布哈希算法進行數據分片和分布式存儲。
- Hazelcast:Hazelcast是一個開源的分布式內存數據網格平臺,提供分布式緩存和分布式計算能力。它可以用于構建高吞吐量和高可用性的分布式緩存系統。
四、分布式緩存問題及解決方案
4.1?緩存穿透
緩存穿透是指數據庫和緩存都沒有的數據,每次都要經過緩存去訪問數據庫,大量的請求有可能導致DB宕機(緩存和數據庫都沒有數據+并發訪問)。
應對策略
- 使用布隆過濾器(Bloom Filter):布隆過濾器是一種快速判斷元素是否存在的數據結構,它可以在很小的內存占用下,快速判斷一個元素是否在一個集合中。將所有可能存在的數據哈希到一個足夠大的位數組中,當一個請求過來時,先經過布隆過濾器判斷是否存在于緩存中,如果不存在,則直接返回,避免對數據庫的查詢壓力。
- 空對象緩存:對于確定不存在的數據,在緩存中也存儲一個空對象,表示該數據不存在。當請求訪問這些不存在的數據時,直接從緩存中返回空對象,避免每次請求都穿透到數據庫層進行查詢。
- 延遲雙判:當一個查詢請求穿透緩存到達數據庫層后,先在數據庫中進行查詢,如果數據庫也沒有對應的數據,則將這個空結果寫入緩存,并設置一個較短的過期時間。這樣,下次相同的查詢請求就會從緩存中得到空結果,而不會再次穿透到數據庫。
- 熱點數據預加載:對于一些熱點數據,在系統啟動時或者在緩存過期前提前異步加載到緩存中,確保緩存的熱點數據一直存在,避免被頻繁請求的數據因為緩存過期而導致穿透問題。
- 限流策略:針對頻繁請求的特定數據,可以設置限流策略,例如使用令牌桶算法或漏桶算法,限制對這些數據的請求頻率,減輕數據庫的壓力。
4.2?緩存擊穿
緩存擊穿是指數據庫有,緩存沒有的熱點數據,大量請求訪問這個緩存不存在的數據,最后請求打到DB可能導致DB宕機 (單個熱點Key過期+并發訪問)。
應對策略
- 設置熱點數據的熱度時間窗口:對于熱點數據,可以設置一個熱度時間窗口,在這個時間窗口內,如果一個數據被頻繁訪問,就將其緩存時間延長,避免頻繁刷新緩存導致緩存擊穿。
- 使用互斥鎖或分布式鎖:在緩存失效時,只允許一個線程去查詢數據庫,其他線程等待查詢結果。可以使用互斥鎖或分布式鎖來實現,確保只有一個線程能夠查詢數據庫,其他線程等待結果,避免多個線程同時查詢數據庫造成數據庫壓力過大。
- 緩存永不過期:對于一些熱點數據,可以將其緩存設置為永不過期,或者設置一個很長的過期時間,這樣即使緩存失效,也有足夠的時間來刷新緩存,避免緩存擊穿。
- 異步更新緩存:在緩存失效時,可以異步地去更新緩存,而不是同步地去查詢數據庫并刷新緩存。這樣可以減少對數據庫的直接訪問,并且不會阻塞其他請求的響應。
- 多級緩存架構:使用多級緩存架構,將熱點數據分散到多個緩存節點上,避免單一緩存節點發生故障導致整個緩存層崩潰。當某個緩存節點失效時,可以從其他緩存節點或數據庫中獲取數據。
- 熔斷機制:當緩存層發生故障或無法正常工作時,可以設置熔斷機制,直接訪問數據庫,保證系統的正常運行。
4.3?緩存雪崩
緩存雪崩指的是在同一時段大量的緩存鍵(key)同時失效,導致大量請求打到數據庫,最后請求打到DB可能導致DB宕機 (批量Key過期+并發訪問)。
應對策略
- 使用多級緩存架構:將緩存劃分為多個層級,每個層級的緩存設置不同的過期時間。例如,將熱點數據存儲在近期失效的緩存層級,而將非熱點數據存儲在長期失效的緩存層級。這樣即使某一層級的緩存失效,仍然可以從其他層級獲取數據,避免所有請求直接訪問數據庫。
- 設置緩存數據的隨機過期時間:在設置緩存數據的過期時間時,加上一個隨機值,使得不同的緩存數據在過期時刻不一致。這樣可以避免大量數據同時過期,減輕數據庫負荷。
- 分布式鎖或互斥鎖:在緩存失效時,使用分布式鎖或互斥鎖來保證只有一個請求可以重新加載緩存。其他請求等待該請求完成后,直接從緩存中獲取數據。這樣可以避免多個請求同時訪問數據庫。
- 數據預熱:在系統啟動或者非高峰期,提前將熱點數據加載到緩存中,預熱緩存。這樣即使在高并發時,也能夠從緩存中獲取到數據,減輕數據庫的壓力。
- 緩存限流:當檢測到緩存失效時,可以對請求進行限流處理,限制并發請求的數量。這樣可以避免大量請求同時訪問數據庫,導致數據庫負載過大。
- 數據庫優化:對于緩存雪崩問題,除了緩存層面的應對策略,還可以從數據庫層面進行優化,如提升數據庫性能、增加數據庫的容量等,以應對大量請求導致的數據庫壓力。
五、緩存一致性問題
緩存一致性指的是緩存與DB之間的數據一致性,我們需要通過各種手段來防止緩存與DB不一致,我們要保證緩存與DB的數據一致或者數據最終一致。
應對策略
針對緩存一致性問題,可以從不同的層次來應對:
(1)數據庫層
- 在數據庫層面,可以使用事務來確保數據的一致性。通過將讀寫操作放在同一個事務中,可以保證數據的更新和查詢是一致的。
- 使用數據庫的觸發器或者存儲過程,在數據更新的同時,主動觸發緩存的更新操作,確保緩存與數據庫的數據保持一致。
(2)緩存層
- 在緩存層面,可以使用緩存更新策略,通過定時任務、異步消息隊列等方式,定期或者在數據更新時異步地更新緩存,保持緩存與數據庫的數據一致性。
- 使用互斥鎖或者分布式鎖來保證對緩存的讀寫操作的原子性,避免數據沖突。
- 設置合適的緩存過期時間,避免緩存數據長時間過期而導致數據不一致的問題。
(3)應用層
- 在應用層面,可以采用讀寫分離策略,將讀請求和寫請求分發到不同的節點,讀請求直接從緩存中獲取數據,寫請求則更新數據庫并更新緩存,保持數據的一致性。
- 使用緩存中間件或者緩存組件,提供自動更新緩存的功能,減少手動維護緩存的復雜性。
(4)監控和報警
- 建立監控和報警機制,通過監控緩存層和數據庫層的狀態、數據一致性等指標,及時發現異常情況,并觸發報警,以便及時處理問題。
六、小結
緩存類型 | 介紹 | 解決方案/工具 | 優點 | 缺點 | 適用場景 |
瀏覽器緩存 | 存儲在用戶設備上的緩存,用于存儲靜態資源和頁面內容。 | 通過設置HTTP頭中的緩存相關字段來控制緩存行為。 | - 快速響應,避免頻繁訪問服務器或網絡 - 減少網絡帶寬消耗,提升網站性能 | - 緩存數據可能不是最新的,需要考慮緩存一致性和更新機制的設計 - 緩存命中率受限于緩存容量和緩存策略的選擇 | - 靜態資源的緩存 - 減少網絡帶寬消耗 |
客戶端緩存 | 應用程序在用戶設備上的緩存,用于存儲數據、計算結果或其他業務相關的內容。 | 使用本地存儲、SessionStorage、LocalStorage或IndexedDB等Web API來進行數據的存儲和讀取。 | - 減輕后端負載,提升系統性能 - 快速響應,避免頻繁訪問服務器或網絡資源 | - 緩存數據可能不是最新的,需要考慮緩存一致性和更新機制的設計 - 緩存命中率受限于緩存容量和緩存策略的選擇 | - 頻繁訪問的數據或計算結果 - 減輕后端負載 |
CDN緩存 | 內容分發網絡的緩存,用于存儲和加速靜態資源的分發。 | 部署靜態資源到CDN服務器并配置CDN緩存策略,用戶請求將被轉發到就近的CDN節點,加速內容的分發和訪問。 | - 加速靜態資源的訪問速度,提升用戶體驗 - 減輕源服務器負載,提高系統可擴展性 | - 只適用于靜態資源的緩存,動態內容無法緩存 - CDN配置和管理的復雜性 | - 靜態資源的分發和訪問 - 加速靜態資源的加載和訪問 |
反向代理緩存 | 位于服務器前端的緩存,用于緩存和加速動態內容和靜態資源的訪問。 | 配置反向代理服務器并設置緩存策略,將用戶請求轉發到緩存服務器,減輕后端服務器的負載并加速內容的訪問。 | - 加速內容的訪問速度,提升用戶體驗 - 減輕源服務器負載,提高系統可擴展性 | - 只適用于特定的Web服務器和應用程序 | - 動態內容和靜態資源的緩存和加速訪問 - 減輕后端服務器的負載 |
本地緩存 | 應用程序在用戶設備上的緩存,用于緩存數據和資源以提高應用的性能和響應速度。 | 使用緩存庫或框架(如localStorage、sessionStorage、Workbox等)來實現本地緩存功能。 | - 提升應用的性能和響應速度 - 減少對遠程資源的依賴,提高離線使用體驗 | - 本地緩存容量受限于用戶設備的存儲空間 | - 頻繁訪問的數據或資源 - 提升應用的性能和響應速度 |
分布式緩存 | 在分布式系統中使用的緩存,用于存儲和共享數據。分布式緩存通常部署在多臺服務器上,并提供高并發讀寫能力和數據訪問的可擴展性。分布式緩存常用于大規模應用和系統中。 | 使用分布式緩存系統(如Redis、Memcached等)來存儲和訪問緩存數據。 | - 高并發讀寫能力和數據存儲的可擴展性 | - 需要額外的服務器資源來部署和管理分布式緩存系統 - 緩存一致性和數據同步問題需要考慮 | - 高并發讀寫能力和數據存儲的可擴展性 - 大規模應用和系統的緩存和數據共享 |
以上是對瀏覽器緩存、客戶端緩存、CDN緩存、反向代理緩存、本地緩存和分布式緩存的橫向對比,包括介紹、解決方案/工具、優點和缺點以及適用場景的詳細信息。根據具體需求和系統架構,選擇適合的緩存類型和方案,以提高系統性能、減輕服務器負載、改善用戶體驗和保證數據一致性。