第十二節:Asp.Net Core 之分布式緩存(SQLServer和Redis)


一. 整體說明

1. 說明

  分布式緩存通常是指在多個應用程序服務器的架構下,作為他們共享的外部服務共享緩存,常用的有SQLServer、Redis、NCache。

    特別說明一下:這里的分布式是指多個應用程序服務器,而不是指將Redis或SQLServer部署成分布式集群。

2. 分布式緩存數據有以下幾個特點

 A. 跨多個服務器請求

 B. 服務器重新啟動和應用部署緩存仍然有效

 C. 不使用本地緩存

本節主要介紹基於SQLServer和Redis的分布式緩存服務,在Asp.Net Core中,主要是基於IDistributedCache接口來實現分布式緩存服務。

3.緩存方法介紹

來自於IDistributedCache接口和DistributedCacheExtensions擴展類。

 A. 讀取:Get、GetString及其對應的異步方法。根據key鍵獲取對應的值,Get方法返回的byte數組,這里更常用GetString方法,返回字符串。

 B. 寫入:Set、SetString及其對應的異步方法。同上,Set操控的是byte數組,這里更常用SetString方法。DistributedCacheEntryOptions,用於配置緩存的性質,下面詳細介紹。

 C. 移除:Remove及其對應的異步方法。根據key鍵來移除緩存。

 D. 刷新重置:Refresh及其對應的異步方法。刷新緩存基於其密鑰,重置其滑動到期超時值(如果有)中的項。

4. 緩存性質介紹

這里通過DistributedCacheEntryOptions類配置,通過F12觀察代碼可知,可以設置以下三個屬性。

 A. DateTimeOffset? AbsoluteExpiration:絕對過期時間,如: new DateTimeOffset(DateTime.Parse("2019-07-16 16:33:10"));

 B. TimeSpan? AbsoluteExpirationRelativeToNow:絕對過期時間,如: TimeSpan.FromSeconds(10);

 C. TimeSpan? SlidingExpiration:相對過期時間,如: TimeSpan.FromSeconds(10);

 

二. SqlServer分布式緩存

1. 前提

  安裝【Microsoft.Extensions.Caching.SqlServer】程序集,如果是Core MVC程序,自帶的Microsoft.AspNetCore.App包里已經涵蓋了該程序集,無需重復安裝。

2. 使用步驟

 A. 在數據庫中新建一個名叫“CacheDB”表,然后以管理員身份cmd運行下面指令,會創建一張名叫“AspNetCoreCache”表,相應的緩存信息都存在於這張表中。

【dotnet sql-cache create "Server=localhost;User=sa;Password=123456;Database=CacheDB" dbo AspNetCoreCache】成功后會提示:Table and index were created successfully.

PS:補充表的結構和含義, 分別是鍵、值、到期時刻(有問題)、滑動過期時間、絕對過期時間。

 B. 在ConfigureService中通過AddDistributedSqlServerCache方法注冊SqlServer緩存服務,可以通過SqlServerCacheOptions對象全局配置緩存的性質。

  (PS:也可以使用的時候通過DistributedCacheEntryOptions類配置)

 1 {
 2   "Logging": {
 3     "LogLevel": {
 4       "Default": "Warning"
 5     }
 6   },
 7   "AllowedHosts": "*",
 8   "SqlSeverConnectionString": "Server=localhost;User=sa;Password=123456;Database=CacheDB",
 9   //暫時沒用到,使用Redis的時候,沒有設置密碼
10   "RedisConnectionString": "172.16.1.250:6379,defaultDatabase=11,name=TestDb,password=Gworld2017,abortConnect=false"
11 }
1  //注冊分布式的SQLServer緩存服務
2  services.AddDistributedSqlServerCache(options =>
3  {
4      options.ConnectionString = Configuration["SqlSeverConnectionString"];
5      options.SchemaName = "dbo";
6      options.TableName = "AspNetCoreCache";
7  });            

 C. 通過構造函數注入IDistributedCache對象

1    public class ThirdController : Controller
2     {
3         public IDistributedCache _cache1 { get; set; }
4 
5         public ThirdController(IDistributedCache cache1)
6         {
7             _cache1 = cache1;
8         }
9     }

 D. 通過GetString和SetString進行讀取和寫入,通過DistributedCacheEntryOptions類配置。

 1   public IActionResult Index()
 2   {
 3 
 4      string nowTime = _cache1.GetString("t1");
 5       if (string.IsNullOrEmpty(nowTime))
 6       {
 7         nowTime = DateTime.Now.ToString();
 8 
 9         DistributedCacheEntryOptions options = new DistributedCacheEntryOptions();
10         //1.相對過期時間
11         //options.SlidingExpiration = TimeSpan.FromSeconds(10);
12 
13         //2. 絕對過期時間(兩種形式)
14         options.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(100);
15         //options.AbsoluteExpiration= new DateTimeOffset(DateTime.Parse("2019-07-16 16:33:10"));
16 
17         _cache1.SetString("t1", nowTime,options);
18       }
19      ViewBag.t1 = nowTime;
20 
21      return View();
22  }

4. 緩存性質的配置

(1) 全局配置

 注冊的時候通過SqlServerCacheOptions類配置,如下圖,必須要配置的三個屬性是:ConnectionString數據連接字符串、SchemaName表架構、Table表名稱。

(2) 使用時配置

 通過DistributedCacheEntryOptions類配置,上面已經介紹了。

5. 擴展緩存清除相關問題

  在緩存過期后,每次調用 Get/GetAsync 方法都會 調用 SqlServerCache 的 私有方法 ScanForExpiredItemsIfRequired() 進行一次掃描, 然后清除所有過期的緩存條目,掃描方法執行過程也很簡單,就是直接執行數據庫查詢語句  DELETE FROM {0} WHERE @UtcNow > ExpiresAtTime .

特別注意:異步方法中同步調用會導致過期的緩存清除不了,所以使用異步的話就異步到底。 await this.cache.GetStringAsync("CurrentTime");

三. Redis分布式緩存

1. 前提

  安裝【Microsoft.Extensions.Caching.StackExchangeRedis】程序集,Core MVC中這個也是不包含的。

2. 使用步驟

 A. 下載Redis程序,打開redis-server.exe,啟動Redis。

 B. 在ConfigureService中通過AddStackExchangeRedisCache方法注冊Redis緩存服務。 必須要設置的是Configuration連接字符串和InstanceName實例名。

1    //注冊分布式的Redis緩存服務
2     services.AddStackExchangeRedisCache(options =>
3     {
4           options.Configuration = "localhost";
5           options.InstanceName = "SampleInstance";
6      });

 C. 通過構造函數注入IDistributedCache對象。

 D. 通過GetString和SetString進行讀取和寫入,通過DistributedCacheEntryOptions類配置。

C D 兩步代碼和上述SqlServer的完全相同。

 1   public class ThirdController : Controller
 2     {
 3         public IDistributedCache _cache1 { get; set; }
 4 
 5         public ThirdController(IDistributedCache cache1)
 6         {
 7             _cache1 = cache1;
 8         }
 9 
10         public IActionResult Index()
11         {
12 
13             string nowTime = _cache1.GetString("t1");
14             if (string.IsNullOrEmpty(nowTime))
15             {
16                 nowTime = DateTime.Now.ToString();
17 
18                 DistributedCacheEntryOptions options = new DistributedCacheEntryOptions();
19                 //1.相對過期時間
20                 //options.SlidingExpiration = TimeSpan.FromSeconds(10);
21 
22                 //2. 絕對過期時間(兩種形式)
23                 options.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(100);
24                 //options.AbsoluteExpiration= new DateTimeOffset(DateTime.Parse("2019-07-16 16:33:10"));
25 
26                 _cache1.SetString("t1", nowTime,options);
27             }
28             ViewBag.t1 = nowTime;
29 
30             return View();
31         }
32     }

3. 緩存方法和緩存性質

  同SqlServer中相同的完全相同

4. 緩存清除與SqlServer的區別

  使用 Redis 分布式緩存允許你在異步方法中調用同步獲取緩存的方法,這不會導致緩存清理的問題,因為緩存的管理已經完全交給了 Redis 客戶端 StackExchange.Redis了

5. 總結

  細心的你可能已經發現了,上面的這段代碼和之前演示的 SqlServerCache 完全一致,是的,僅僅是修改一下ConfigureService注冊的方法,我們就能在項目中進行無縫的切換;但是,對於緩存有強依賴的業務,建議還是需要做好緩存遷移,確保項目能夠平滑過渡。

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 本人才疏學淺,用郭德綱的話說“我是一個小學生”,如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM