使用快取(Cache)的幾種方式,回顧一下~~~
- 2022 年 3 月 31 日
- 筆記
- .netcore, 跟我一起學.NetCore
前言
如今快取成為了優化網站性能的首要利器,快取使用的好,不僅能讓網站性能提升,讓用戶體驗變好,而且還能節約成本(增加一台快取伺服器可能就節約好幾台機器);那平時小夥伴們都使用哪些快取方式呢?這裡就來和小夥伴們一起來回顧一下。
正文
快取的作用其實很明確,如下兩方面:
-
提升數據的獲取速度
通常用在獲取數據速度要求比較高的場景,比如一些和設備通訊的軟體,對時間的要求比較高,如果每次都從資料庫讀數據會導致消耗多餘的時間。
-
減輕後台應用或資料庫伺服器的負載
對於高並發場景的系統,如果每次請求都打到資料庫,資料庫伺服器負載會變大,到達一定瓶頸之後可能讓系統體驗變差或不可用。
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中讀取到的數據一致,過期之後就會清空,程式又會設置新的值,如下:
關於快取的幾種用法就先暫時說這麼多,也有小夥伴根據業務場景自己實現的。
實例的源碼://gitee.com/CodeZoe/dot-net-core-study-demo/tree/main/CacheDemo
總結
快取之所以現在這麼火,其主要目的還是提升數據訪問效率,緩解應用和資料庫的壓力,但同時也會帶來一些問題,比如快取穿透、快取擊穿、快取雪崩及快取數據與資料庫不一致等問題,後續我們會逐個說說,關注「Code綜藝圈」,和我一起學習吧。