緩存

1. What——什麼是緩存?

從定義上可以看出所謂緩存一定是針對已有數據的一個副本存在,也可以看出緩存的使用是爲了解決快速訪問數據(讀數據)的場景。在現有的互聯網應用中,緩存的使用是一種能夠提升服務快速響應的關鍵技術。

緩存在計算機領域中實際案例存在很多,比如CPU的緩存是爲了解決CPU的運算速度和內存的讀取數據不平衡的問題,CPU的運算速度遠快與內存的讀寫速度,爲了降低CPU等待數據讀寫的時間,在CPU中引入L1/L2/L3多級緩存。

再比如Linux中的文件緩存,實際上我們在編程時,會談論到數據的內存地址,但是我們接觸的都是虛擬地址而不是真實的物理地址,計算機中的內存管理單元(MMU)和頁表會將虛擬地址轉換成物理地址。在計算機硬件領域中就已有很多關於緩存的應用案例,實際上在軟件架構中關於緩存的設計會借鑑於很多傳統且成熟的計算機硬件緩存設計的思想。

2. Why——爲什麼需要使用緩存?

1)極大的提升軟件用戶體驗

2)提升吞吐量

3. Where——緩存存在鏈路中的哪些地方?

3.1 緩存分類

從一個請求到最終獲取響應,會經過很多環節,緩存可以幾乎存在整個鏈路的每個節點。緩存按照不同的維度可以有如下分類:

1)緩存所處鏈路節點的位置:
客戶端緩存

網絡緩存

服務端緩存

2)緩存架構部署方式:
單機緩存

緩存集羣

分佈式緩存

3)緩存的內存區域
本地緩存/進程內緩存

進程間緩存

遠程緩存

按照緩存在服務鏈路上的位置來劃分,可以系統性的梳理下緩存的不同應用。

3.2 客戶端緩存

客戶端緩存是離用戶“最近”的一種存儲介質,經常和網絡測和服務端緩存一起配合使用,常見的客戶端緩存有如下幾種:

1)頁面緩存:頁面緩存是指將靜態頁面獲取頁面中的部分元素緩存到本地,以便下次請求不需要重複資源文件,h5很好的支持的離線緩存的功能,具體實現可通過頁面指定manifest文件,當瀏覽器訪問一個帶有manifest屬性的文件時,會先從應用緩存中獲取加載頁面的資源文件,並通過檢查機制處理緩存更新的問題。

2)瀏覽器緩存:瀏覽器緩存通常會專門開闢內存空間以存儲資源副本,當用戶後退或者返回上一步操作時可以通過瀏覽器緩存快速的獲取數據,在HTTP 1.1中通過引入e-tag標籤並結合expire、cache-control兩個特性能夠很好的支持瀏覽器緩存,關於瀏覽器緩存更爲細節的知識可以查看該文章。

3)APP緩存:APP可以將內容緩存到內存或者本地數據庫中,例如在一些開源的圖片庫中都具備緩存的技術特性,當圖片等資源文件從遠程服務器獲取後會進行緩存,以便下一次不再進行重複請求,並可以減少用戶的流量費用。

客戶端緩存是前端性能優化的一個重要方向,畢竟客戶端是距離“用戶”最近的地方,是一個可以充分挖掘優化潛力的地方。

3.3 網絡緩存

網絡緩存位於客戶端以及服務端中間,通過通過代理的方式解決數據請求的響應,降低數據請求的回源率。通常具有如下幾種形式的網路緩存:

1)web代理緩存:常見的代理形式分爲分爲:正向代理、反向代理以及透明代理。web代理緩存通常是指正向代理,會將資源文件和熱點數據放在代理服務器上,當新的請求到來時,如果在代理服務器上能獲取數據,則不需要重複請求到應用服務器上;

2)邊緣緩存:和正向代理一樣,反向代理同樣可以用於緩存,例如nginx就提供了緩存的功能。進一步,如果這些反向代理服務器能夠做到和用戶請求來自同一個網絡,那麼獲取資源的速度進一步提升,這類的反向代理服務器可以稱之爲邊緣緩存。常見的邊緣緩存就是CDN(Content Delivery Network),可以將圖片等靜態資源文件放到CDN上。

3.4 服務端緩存

服務端緩存是後端開發中進行性能優化的發力點,常見的後端性能優化也是通過引入緩存來進行解決,常見的有數據庫的查詢緩存、緩存框架以及引入應用級緩存。

★ 3.4.1 數據庫查詢緩存

例如,MySQL的緩存機制是通過將SELECT語句以及相應的ResultSet進行緩存,當後續接受到SELECT請求後,如果MySQL已經開啓了Query Cache功能,會將SELECT語句以字符串的方式進行hash,然後去從緩存中進行查詢,如果查詢出數據,則直接進行返回,省去了後續的優化器以及存儲引擎IO的操作,能夠極大的提升響應時效。如何優化Query Cache需要從如下幾個指標上進行考慮:

query_cache_size:設置能夠緩存ResultSet的內存區域大小
query_cache_type:表示使用緩存的場景。0表示任何場景下都不使用Query Cache,1表示顯式指定不使用Query Cache的查詢都可以使用,2(DEMAND)表示只有明確指示使用Query Cache纔會生效;
Qcache hits:表示多少次查詢命中Query Cache
Qcache inserts:表示多少次沒有命中Query Cache而插入數據
Qcahce lowmem prunes:表示多少條Query引入空間不足而被清除
Qcache free memory:表示剩餘內存大小
Qcache free blocks:該值很大表示內存碎片很多,需要及時清理

在進行Qcache優化時,可以對以上指標綜合進行分析,比如瞭解Qcache的緩存命中率 = Qcache hits/ Qcache hits + Qcache inserts,來判斷當前Qcache的效率。也可以結合Qcahce lowmem prunes、Qcache free memory以及Qcache free blocks來判斷當前Qcache的內存使用效率。

另外,如果使用Innodb存儲引擎的話,也需要着重關注innodb_buffer_pool_size參數,該參數決定了innodb的索引以及數據是否有足夠大的空間放入到緩存中。table_cache決定了能夠緩存表的最大數量,也是需要關注的一個參數。

★ 3.4.2 緩存框架

在功能開發時,會常用提供緩存特性的緩存框架或者實現緩存功能的類庫來高效的完成開發,常見的緩存框架有Ehcache、Guava等,這些緩存框架配置簡單,能夠簡單靈活的使用。這些開源的緩存框架不僅支持單機的本地緩存還能配置集羣的方式達到靈活伸縮。

★ 3.4.3 應用級緩存

當緩存框架不能滿足需求的時候,就需要引入應用級緩存,比如Redis、MongoDB等NoSQL數據庫,應用級緩存具備高可用性以及伸縮性的分佈式架構能夠支撐業務需求,當然,做好一款應用級緩存產品其中的挑戰也是巨大。

4. When——什麼時候需要使用緩存?

緩存不是架構設計的必選項,也不是業務開發中的必要功能點,只有在業務出現性能瓶頸,進行優化性能的時候才需要考慮使用緩存來提升系統性能。也不是所有的業務場景都適合使用緩存,讀多寫少且數據時效要求越低的場景越適合使用緩存,緩存並不是所有性能問題的靈丹妙藥,如果濫用緩存反而會成爲毒藥,並且會引入維護緩存的操作成本,使得系統複雜度更高不利於維護。

另外把緩存當做存儲來使用是一件極其致命的做法,這種錯誤的認識,將緩存引入系統的那一刻起就意味着已經讓系統走上了危險的局面,對緩存的使用邊界要有深刻的理解,才能儘可能保證做出引入緩存纔是一個正確的決定。

在進行緩存結構設計的時候,需要考慮的點有很多:

1)業務流量量級以及應用規模:對於低併發低流量的應用而言,引入緩存並不會帶來性能的顯著提升,反而會帶來應用的複雜度以及極高的運維成本。也不是任何數據都需要使用緩存,比如圖片視頻等文件使用分佈式文件系統更合適而不是緩存。因此,在引入緩存前,需要對當前業務的流量進行評估,在高併發大流量的業務場景中引入緩存相對而言收益會更高;

2)緩存應用的選擇:緩存應用有很多如Redis、Memcached以及tair等等,針對每一種分佈式緩存應用的優缺點以及適用範圍、內存效率、運維成本甚至團隊開發人員的知識結構都需要了解,才能做好技術選型;

3)緩存影響因素的正確評估:在引入緩存前,需要着重評估value大小、緩存內存空間、峯值QPS、過期時間、緩存命中率、讀寫更新策略、key值分佈路由策略、過期策略以及數據一致性方案等等多個因素,要做到心中有數;

4)緩存高可用架構:分佈式緩存要高可用,這也是分佈式系統追求的三高指標中的一個,緩存的集羣設計,主從同步方案的設計等等,只有緩存足夠可靠,才能服務於業務系統,爲業務帶來價值;

5)完善的監控平臺:當緩存投入生產環境後,需要有一套監控系統能夠顯式的觀測緩存系統的運行情況,才能更早的發現問題,同時對於預估不足的非預期熱點數據,也需要熱點發現系統去解決非預期的熱點數據緩存問題。

6)緩存最近原則:將緩存數據放在離用戶最近的地方,無疑會極大的提升響應的速度,這也是多級緩存設計的核心思想。

5.如何正確使用緩存?

影響緩存整體的性能會有很多大大小小的影響因素,比如語言本身的特性的影響,例如Java需要考慮GC的影響。還需要儘可能的提升緩存命中率等等多個方面,核心的幾個影響因素有哪些?如何正確使用?

https://developer.aliyun.com/article/728028?spm=a1z389.11499242.0.0.65452413JPs6l3&utm_content=g_1000089486

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章