緩存是搭建高性能高併發系統的必備手段之一,一般用來解決性能瓶頸,是程序員的必備知識點,也是面試必備考點。前端
儘管,產品經理大機率不會關注系統性能,但程序員在實現需求的時候必須思考系統承載的併發量和用戶量。緩存主要用來解決性能瓶頸的問題,一旦錯誤使用反而會令系統崩潰。今天,咱們就經過4W的方式系統化地總結緩存相關的理論知識。
隨着互聯網業務的快速迭代以及用戶量激增,應用架構須要不斷調整甚至重構以適應這種業務的快速發展。當數據量迅速增加,業務邏輯越複雜,服務鏈路不斷增長等等一系列問題,會致使RT過長,服務性能須要逐漸提高以知足更優的用戶體驗。在優化系統架構時一般的所用的兩種方式scale up以及scale out,scale out就是一般所說的水平擴展,將應用服務設計成無狀態性,能夠方便水平擴展經過增長硬件的方式分解訪問壓力。而scale up則是將單個服務鏈路性能提高,以提高QPS以及系統的吞吐量。在追求更優的性能時,大多數業務場景是讀多寫少的狀況,通常會經過引入緩存的方式解決。nginx
- What——什麼是緩存?
關於緩存的定義,在wiki中爲:
a collection of data duplicating original values stored elsewhere on a computer, usually for easier access.
簡單理解就是保存在計算機設備中的一個數據副本,以便於後續可以進行快速訪問。
從定義上能夠看出所謂緩存必定是針對已有數據的一個副本存在,也能夠看出緩存的使用是爲了解決快速訪問數據(讀數據)的場景。在現有的互聯網應用中,緩存的使用是一種可以提高服務快速響應的關鍵技術,也是產品經理無暇顧及的非功能需求,須要在設計技術方案時對業務場景,具備必定的前瞻性評估後,決定在技術架構中是否須要引入緩存解決這種這種非功能需求。
緩存在計算機領域中實際案例存在不少,好比CPU的緩存是爲了解決CPU的運算速度和內存的讀取數據不平衡的問題,CPU的運算速度遠快與內存的讀寫速度,爲了下降CPU等待數據讀寫的時間,在CPU中引入L1/L2/L3多級緩存。
再好比Linux中的文件緩存,實際上咱們在編程時,會談論到數據的內存地址,可是咱們接觸的都是虛擬地址而不是真實的物理地址,計算機中的內存管理單元(MMU)和頁表會將虛擬地址轉換成物理地址。在計算機硬件領域中就已有不少關於緩存的應用案例,實際上在軟件架構中關於緩存的設計會借鑑於不少傳統且成熟的計算機硬件緩存設計的思想。
- Why——爲何須要使用緩存?
軟件服務可以獲得用戶的信賴,並將產品的價值帶給用戶,可以解決目標用戶的痛點問題這是決定用戶會不會一開始決定使用,也就是《增加***》中提到了產品可以帶來給用戶「啊哈時刻」,而決定用戶會不會高頻使用以及持續使用,用戶體驗則是被認爲是軟件產品提高用戶黏性的關鍵影響因素。
2.1 什麼是用戶體驗
用戶體驗被專業定義和推廣須要推廣到20世紀90年代,由Donald Norman佈道推廣。用戶體驗在人機交互領域上受到了重視,並一度和傳統的三大可用性指標(即效率、效益以及基本滿意度)不相上下。
ISO 9241-210標準將用戶體驗官方定義爲:人們對正在使用或者期待使用的產品、系統或者服務的認知印象和迴應。能夠看出用戶體驗是用戶的對軟件產品的主觀感覺,具體包含了用戶在使用以前、使用中以及使用後的情感、喜愛、認知印象、心理反應以及情緒表達等等多種主觀感覺,每一個用戶對產品的主觀感覺的視角不一樣,關注點不一樣,也就致使軟件產品讓大多數用戶都可以得到很好的用戶體驗自己就是一件頗有挑戰性的事情。
在業界大多數,將用戶體驗分爲三類:使用者狀態、軟件產品的系統性能以及環境,使用者狀態以及環境(使用者環境以及產品在同類產品中的產品大環境)這兩個因素須要交互設計和用研等多個專業領域同窗去攻克,軟件開發者則須要解決系統性能的問題。對用戶而言,最基本的需求就是在使用軟件服務時,軟件產品提供服務內容的及時性,也就是一般所說的在使用過程當中持續的Loading(轉菊花)必定會致使用戶體驗不好,內容的及時性也是系統性能的最低要求。
而系統性能的問題,是產品經理無暇顧及的點,也是非功能性需求,須要開發者去花心思去思考的地方。評估系統性能的指標有不少,在以提高用戶體驗爲前提的狀況下,咱們須要着重關注的性能指標有哪些呢?
2.2 常見的性能指標
在設計軟件架構時須要關注的幾個常見指標:響應時間、延遲時間、吞吐量、併發用戶數和資源利用率。
1)系統響應時間 :響應時間是指系統對用戶請求作出響應的時間,不一樣的功能的鏈路長短不一樣,而且同一功能在不一樣數據量等這些狀況都會致使響應時間的不一樣。所以,在衡量系統響應時間時,一般會關注軟件產品全部功能的平均響應時間以及最大響應時間。
2)延遲時間 :在討論系統響應時間時,更細粒度的劃分能夠劃分爲:
客戶端在接受數據進行渲染的內容「呈現時間」;
服務端在接受用戶請求發送至服務端以及服務端將數據返回到客戶端這兩個過程當中涉及到的:網絡傳輸時間以及應用延遲時間。應用延遲時間便是服務端在執行整個服務鏈路時所花費的時間,也是性能優化首要下降的就是這個時間。
3)吞吐量 :吞吐量指的是單位時間內可以處理請求的數量,對於無併發的應用來講,吞吐量和請求響應時間成反比,服務延遲更長則系統吞吐量更低。
4)併發用戶數 :併發用戶數指的是系統可以同時承載正常使用系統功能的用戶數,相較於吞吐量,這個指標更爲籠統可是對於非軟件領域的人來講更容易理解。
5)資源利用率 :資源利用率反映的是在一段時間內資源被佔用的狀況。
2.3 緩存帶來的優點
在追求更優的優化體驗時,客觀的來講須要不斷提高以上這些性能指標,不斷逼近系統體驗的最優解。緩存到底具備什麼樣的優點,值得咱們花費很大的精力去設計一套能很好的適應如今的業務場景的緩存結構呢?
1)極大的提高軟件用戶體驗
軟件產品主要圍繞兩個核心問題,一是解決目標用戶的痛點問題,二是提高產品黏性。在提供軟件服務時,抽象的來看是解決數據在整個鏈路上的流轉問題,如何讓數據流轉更加高效、更加順暢是在實現時着重關注的地方,事實上,不管是瀏覽器、負載均衡、應用服務器仍是數據庫等等各個環節都會應用到緩存,當數據離用戶「更近」,好比數據副本在客戶端上,也就意味着請求可以很快的進行響應,相應的給用戶進行數據呈現的耗時就更短。現現在用戶爸爸們「日理萬機」,若是一個軟件產品不能在很短期就獲取用戶的注意力,很大可能性就意味着失敗。所以,使用緩存可以讓用戶從主觀上獲取更優的用戶體驗。
2)提高吞吐量
試想,若是在服務鏈路上,請求可以在緩存中獲取服務數據的話,也就意味着不少數據並不須要從源應用服務器進行獲取,下降了源服務器網絡傳輸的頻率,在必定IDC帶寬下,系統可以下降網絡傳輸時間以及應用延遲時間,從而支撐更多的系統訪問以提高系統總體吞吐量以及併發用戶數,硬件的使用效率也會明顯提高。
從實際場景下,在系統性能優化時大機率會優先選擇使用緩存進行系統優化,也是一種被證實有效的手段,緩存也被認爲是一種「空間換時間」的藝術。
- 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數據庫,應用級緩存具有高可用性以及伸縮性的分佈式架構可以支撐業務需求,固然,作好一款應用級緩存產品其中的挑戰也是巨大。
- When——何時須要使用緩存?緩存不是架構設計的必選項,也不是業務開發中的必要功能點,只有在業務出現性能瓶頸,進行優化性能的時候才須要考慮使用緩存來提高系統性能。也不是全部的業務場景都適合使用緩存,讀多寫少且數據時效要求越低的場景越適合使用緩存,緩存並非全部性能問題的靈丹妙藥,若是濫用緩存反而會成爲毒藥,而且會引入維護緩存的操做成本,使得系統複雜度更高不利於維護。另外把緩存當作存儲來使用是一件極其致命的作法,這種錯誤的認識,將緩存引入系統的那一刻起就意味着已經讓系統走上了危險的局面,對緩存的使用邊界要有深入的理解,才能儘量保證作出引入緩存纔是一個正確的決定。在進行緩存結構設計的時候,須要考慮的點有不少:1)業務流量量級以及應用規模:對於低併發低流量的應用而言,引入緩存並不會帶來性能的顯著提高,反而會帶來應用的複雜度以及極高的運維成本。也不是任何數據都須要使用緩存,好比圖片視頻等文件使用分佈式文件系統更合適而不是緩存。所以,在引入緩存前,須要對當前業務的流量進行評估,在高併發大流量的業務場景中引入緩存相對而言收益會更高;2)緩存應用的選擇:緩存應用有不少如Redis、Memcached以及tair等等,針對每一種分佈式緩存應用的優缺點以及適用範圍、內存效率、運維成本甚至團隊開發人員的知識結構都須要瞭解,才能作好技術選型;3)緩存影響因素的正確評估:在引入緩存前,須要着重評估value大小、緩存內存空間、峯值QPS、過時時間、緩存命中率、讀寫更新策略、key值分佈路由策略、過時策略以及數據一致性方案等等多個因素,要作到心中有數;4)緩存高可用架構:分佈式緩存要高可用,這也是分佈式系統追求的三高指標中的一個,緩存的集羣設計,主從同步方案的設計等等,只有緩存足夠可靠,才能服務於業務系統,爲業務帶來價值;5)完善的監控平臺:當緩存投入生產環境後,須要有一套監控系統可以顯式的觀測緩存系統的運行狀況,才能更早的發現問題,同時對於預估不足的非預期熱點數據,也須要熱點發現系統去解決非預期的熱點數據緩存問題。6)緩存最近原則:將緩存數據放在離用戶最近的地方,無疑會極大的提高響應的速度,這也是多級緩存設計的核心思想。5.如何正確使用緩存?影響緩存總體的性能會有不少大大小小的影響因素,好比語言自己的特性的影響,例如Java須要考慮GC的影響。還須要儘量的提高緩存命中率等等多個方面,核心的幾個影響因素有哪些?如何正確使用?