前言
如今快取成為了優化網站效能的首要利器,快取使用的好,不僅能讓網站效能提升,讓使用者體驗變好,而且還能節約成本(增加一臺快取伺服器可能就節約好幾臺機器);那平時小夥伴們都使用哪些快取方式呢?這裡就來和小夥伴們一起來回顧一下。
正文
快取的作用其實很明確,如下兩方面:
-
提升資料的獲取速度
通常用在獲取資料速度要求比較高的場景,比如一些和裝置通訊的軟體,對時間的要求比較高,如果每次都從資料庫讀資料會導致消耗多餘的時間。
-
減輕後臺應用或資料庫伺服器的負載
對於高併發場景的系統,如果每次請求都打到資料庫,資料庫伺服器負載會變大,到達一定瓶頸之後可能讓系統體驗變差或不可用。
1. 瀏覽器快取
1.1 簡述
通過控制響應頭資訊,告訴瀏覽器讓其將對應的資料快取到本地,在指定時間範圍內,可直接從本地快取中取即可,但瀏覽器方可以不選擇走快取。
1.2 案例演示
本文中還是使用WebAPI專案進行演示,只是通過不同的API來區分不同案例。
建立好專案中,在預設的WeatherForecastController中新增一個Action方法,如下:
這個時候還沒有做快取處理,所以只要訪問都會呼叫介面獲取最新的資料。
在介面方法上只需新增ResponseCache特性就可以實現瀏覽器快取,如下:
這樣就可以實現客戶端快取了,可能會有小夥伴會點選瀏覽器的重新整理和F5進行測試,這個時候並沒有看到快取效果,其實這個時候瀏覽器是以新的請求發出的,並不會去快取裡取,但其實請求獲取到的資料已經存快取了。
那怎麼去測試呢?每次都 開啟多個瀏覽器標籤或用Swagger的形式,如下:
第一次訪問:
每次都開啟新標籤,再訪問介面:
除了根據資料沒變來判定是快取資料外,還可以通過請求確定是否從本地快取中取資料,如下:
Swagger演示,關於如何整合Swagger,之前有專門分享過(跟我一起學.NetCore之Swagger讓前後端不再煩惱及介面自定義):
瀏覽器快取的原理其實就是在響應頭中增加Cache-Control(ResponseCache的方式是通過Action過濾器的形式設定的響應頭),告訴瀏覽器進行資料快取,在指定時間範圍內可以從快取中取,我們也可以自己手動設定響應頭資訊來達到同樣的效果,如下:
儘管資料已經快取,瀏覽器也可以選擇不從快取取,如下:
2. 伺服器快取
2.1 簡述
瀏覽器快取只是將資料儲存在單臺電腦的不同位置,如果開啟不同的瀏覽器或不同的電腦訪問時,還是起不到快取的效果,所以搞個伺服器快取肯定是個不錯的選擇。
即將資料快取到站點伺服器中,當請求過來時,如果命中快取,直接獲取返回即可,不呼叫對應的後臺API。
2.2 案例
其實這只是在原來瀏覽器快取的基礎上增加了一箇中介軟體的處理,如下:
程式碼如下:
執行效果:
由於不同的瀏覽器儲存的資料位置不一樣,如果僅僅是本地快取,那麼兩個瀏覽器的資料會返回不一樣;另外第一個瀏覽器訪問之後,其他瀏覽器在時間範圍內獲得結果是一樣的,也不會呼叫後臺介面。
這種伺服器端的快取在有些情況是不生效的,如:請求Method不是Get或Head的不快取,返回狀態碼不是200的不快取,請求頭包含Authorization的不快取等,所以基本很少用這種方式進行快取操作。
3. 應用記憶體快取
3.1 簡述
對於上面說到的瀏覽器快取和伺服器快取,如果是友好的使用者訪問,沒問題,能起到一定的效果;但如果有人要使壞,不設定對應的請求頭訪問API(禁用快取),最終還是會給應用伺服器和資料庫伺服器帶來壓力。所以需要一種能主動控制的快取方式,後端程式就是下手的物件,在後端程式中寫快取邏輯,這樣快取策略就由我們自己控制了。
雖然每次請求都會進入應用程式,但會先從快取中進行獲取資料,如果命中快取,就不再進行資料庫訪問,直接將快取資料返回。
3.2 案例
其實框架中針對記憶體快取這塊已經做好了封裝,只需註冊相關的服務就可以用了,如下:
註冊完成之後,只需要注入就可以使用了,這裡增加一個Action方法進行演示:
效果就不截圖了,在20秒內,單程式部署情況下,不管怎麼訪問都會是一樣的結果。如果想更多瞭解MemoryCache的使用,可以看看這篇文章《因MemoryCache鬧了個笑話》。
4. 分散式快取
4.1 簡述
記憶體快取雖然能解決瀏覽器和伺服器快取的缺點,但只對單體部署程式比較適用,對於需要分散式部署的程式來說,程式記憶體之間的快取資料不能共享,快取的效果肯定就沒那麼盡人意,所以分散式快取就出來了,採用對應的中介軟體,如Memcache、Redis等,而Redis成為了快取的首選。
請求的邏輯和記憶體快取差不多一樣,只是分散式快取會採用第三方中介軟體進行資料儲存,保證分散式部署的程式共用一套快取。
4.2 案例
這裡還是用最火的Redis做演示,所以需要提前安裝Redis,關於Redis系列的文章,小夥伴們可以看這《給我一起學Redis》。
框架也提供了統一操作分散式快取的介面IDistributedCache,用法和上面的記憶體快取基本一樣。
這裡用的是Redis,所以需要安裝對應的Nuget包Microsoft.Extensions.Caching.StackExchangeRed,然後註冊相關服務就可以用了,如下:
註冊完成之後,只需要注入就可以使用了,這裡也增加一個Action方法進行演示:
訪問對應的介面,在設定的時間範圍內從Redis中讀取到的資料一致,過期之後就會清空,程式又會設定新的值,如下:
關於快取的幾種用法就先暫時說這麼多,也有小夥伴根據業務場景自己實現的。
例項的原始碼:https://gitee.com/CodeZoe/dot-net-core-study-demo/tree/main/CacheDemo
總結
快取之所以現在這麼火,其主要目的還是提升資料訪問效率,緩解應用和資料庫的壓力,但同時也會帶來一些問題,比如快取穿透、快取擊穿、快取雪崩及快取資料與資料庫不一致等問題,後續我們會逐個說說,關注“Code綜藝圈”,和我一起學習吧。