.netcore入門18:aspnetcore分佈式緩存(分佈式內存、sqlserver、redis)

環境:

  • aspnetcore 3.1.1
  • vs2019 16.4.5

.netcore的本地緩存請參考:.net core中使用緩存之MemoryCache(本機內存)

一、分佈式緩存介紹

分佈式的緩存由多個應用程序服務器共享,緩存中的信息不存儲在單獨的 Web 服務器的內存中,並且緩存的數據可用於所有應用服務器。這具有幾個優點:

  • 所有 Web 服務器上的緩存數據都是一致的。
  • 緩存的數據在 Web 服務器重新啓動後和部署後仍然存在。
  • 對數據庫的請求變的更少 。

aspnetcore框架定義了分佈式緩存的接口IDistributedCache,我們在自己的代碼中應該與這個接口做交互,同樣,aspnetcore平臺上的所有分佈式緩存實現也應該實現這個接口。我們來看下這個接口定義的方法:

  • Get,GetAsync :
    接受字符串鍵,並檢索緩存項作爲 byte[] 數組(如果在緩存中找到)。
  • Set,SetAsync:
    使用字符串鍵將項(作爲 byte[] 數組)添加到緩存中。
  • Refresh,RefreshAsync :
    基於其鍵刷新緩存中的項,並重置其可調過期超時值(如果有)。
  • Remove,RemoveAsync:
    會根據其字符串鍵刪除緩存項。

aspnetcore已經內置了分佈式內存緩存,並以nuget包形式提供了分佈式 SQL Server 緩存和分佈式 Redis 緩存的實現,下面具體看一下:

二、分佈式內存緩存:

aspnetcore提供的這個緩存實現是爲了開發測試用的,其實它並沒有實現真正的分佈式。你觀察它的源碼後會發現,它內部調用的還是IMemoryCache。下面看一下它的使用方式:

2.1 第一步:向容器註冊服務

public void ConfigureServices(IServiceCollection services)
{
    services.AddDistributedMemoryCache();
}

2.2 第二步:Controller中調用

namespace _2webapidemo.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
        private readonly ILogger<WeatherForecastController> _logger;
        private readonly IDistributedCache distributedCache;
        public WeatherForecastController(ILogger<WeatherForecastController> logger,/* IMemoryCache cache, */IDistributedCache distributedCache)
        {
            _logger = logger;
            this.distributedCache = distributedCache;
        }
        [HttpGet]
        public async Task<IEnumerable<WeatherForecast>> Get()
        {
            #region 測試分佈式內存緩存
            var key = Guid.NewGuid().ToString();
            var message = "Hello, World!";
            var value = Encoding.UTF8.GetBytes(message);
            Console.WriteLine("Connecting to cache");
            Console.WriteLine("Connected");
            Console.WriteLine("Cache item key: {0}", key);
            Console.WriteLine($"Setting value '{message}' in cache");
            await distributedCache.SetAsync(key,value,new DistributedCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(10)));
            Console.WriteLine("Set");
            Console.WriteLine("Getting value from cache");
            value = await distributedCache.GetAsync(key);
            if (value != null)
            {
                Console.WriteLine("Retrieved: " + Encoding.UTF8.GetString(value, 0, value.Length));
            }
            else
            {
                Console.WriteLine("Not Found");
            }
            Console.WriteLine("Refreshing value in cache");
            await distributedCache.RefreshAsync(key);
            Console.WriteLine("Refreshed");
            Console.WriteLine("Removing value from cache");
            await distributedCache.RemoveAsync(key);
            Console.WriteLine("Removed");
            Console.WriteLine("Getting value from cache again");
            value = await distributedCache.GetAsync(key);
            if (value != null)
            {
                Console.WriteLine("Retrieved: " + Encoding.UTF8.GetString(value, 0, value.Length));
            }
            else
            {
                Console.WriteLine("Not Found");
            }
            #endregion

            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

上面代碼的控制檯輸出如下圖:
在這裏插入圖片描述

三、分佈式SqlServer緩存

aspnetcore框架提供的這個實現可以讓我們很方便的把sqlserver當成一個緩存容器,它的源碼也很簡單,就是對一張緩存表的增刪改查。我們看一下它的源碼文件:
在這裏插入圖片描述
有興趣的可以點開看看裏面的內容,裏面操作數據庫沒有依賴EFCore,而是直接使用的SqlConnection、SqlCommand等這些原始對象。下面來看一下它的使用步驟:

3.1 第一步:準備sqlserver數據庫

你可以手動建表或者是使用dotnet sql-cache工具自動建表,兩種方法任選其一,但是要注意三個名稱“數據庫名稱”、“模式名稱”和“表名稱”,因爲這三個名稱要在代碼中進行配置。下面以數據庫testdbo下的表global_cache爲例說明兩種方案:

3.1.1 方案1:手動建表

直接執行下面腳本即可:

--****************<global_cache>**************
if exists (select 1  
            from  sysobjects  
           where  id = object_id('global_cache')  
            and   type = 'U')  
begin
   drop table global_cache  
   print '已刪除表:global_cache'
end
go 
create table [global_cache] (
    [Id] nvarchar(449) not null   unique,
    [Value] varbinary(max) not null   ,
    [ExpiresAtTime] datetimeoffset(7) not null   ,
    [SlidingExpirationInSeconds] bigint    ,
    [AbsoluteExpiration] datetimeoffset(7)    
) 
ALTER TABLE [global_cache] ADD CONSTRAINT PK_gene_global_cache_Id PRIMARY KEY(Id)
--************索引<Index_ExpiresAtTime>*****************
CREATE NONCLUSTERED INDEX Index_ExpiresAtTime ON global_cache(ExpiresAtTime)
--************索引</Index_ExpiresAtTime>*****************
print '已創建:global_cache'
--****************</global_cache>**************

3.1.2 方案2:使用dotnet sql-cache工具:

這種方法是微軟官方提供的(參考:分佈式 SQL Server 緩存

1)、首先,你要確保你電腦中安裝了sql-cache工具,如果沒有的話,在cmd中執行如下命令安裝:

dotnet tool install --global dotnet-sql-cache --version 3.1.1

注意,sql-cache的版本要和.netcore的版本保持一致,否則,建議卸載重裝,卸載的命令如下:

dotnet tool uninstall dotnet-sql-cache --global

2)、然後, 執行如下命令建表

dotnet sql-cache create "Data Source=.;Initial Catalog=test;User ID=sa;Password=xxxxxx;" dbo global_cache

執行完後提示:“Table and index were created successfully.” 則表示建表成功!

3.3 第二步:引入nuget包

雖然微軟默認提供了分佈式SqlServer緩存的實現,但並沒有集成到aspnetcore框架中,所以我們需要將nuget包引入進來:
在這裏插入圖片描述

3.2 第二步:向容器註冊服務

public void ConfigureServices(IServiceCollection services)
{
    services.AddDistributedSqlServerCache(options=>
    {
        options.ConnectionString = "Data Source=.;Initial Catalog=test;User ID=sa;Password=sa;";
        options.SchemaName = "dbo";
        options.TableName = "global_cache";
    });
    services.AddControllers();
}

3.3 第三步:Controller中調用

同分布式內存。

附:程序運行過程中sqlserver數據庫中存儲的情況:
在這裏插入圖片描述

四、分佈式Redis緩存

redis服務器搭建參考:redis入門(1): linux下安裝redis與簡單配置
redis客戶端下載地址:
鏈接:https://pan.baidu.com/s/1l2NPkhgVdnEM89vpJIwGfA
提取碼:beg4
說明:
aspnetcore中分佈式Redis緩存的源碼很簡單,因爲它對redis的操作依賴於StackExchange.Redis,先來看看它的源碼文件有哪些:
在這裏插入圖片描述
可以看到源碼非常少。我們知道redis中有五大數據類型:string(字符串)、hash(哈希)、list(列表)、set(集合)和zset(sorted set:有序集合),這個分佈式緩存實現的時候僅使用了hash(哈希)這一種格式進行存儲。下面直接看使用步驟:

4.1 第一步:準備redis服務

假設你已經準備好了redis服務爲:
ip:192.168.3.28
port:6379
password:123456

4.2 第二步:引入nuget包

雖然微軟默認實現了分佈式redis緩存,但是並未將程序集集成在aspnetcore框架裏面,所以需要我們手動添加上去:
在這裏插入圖片描述

4.3 第三步:向容器註冊服務

public void ConfigureServices(IServiceCollection services)
{
    services.AddStackExchangeRedisCache(options =>
    {
        //options.Configuration = "192.168.3.28:6379";
        options.ConfigurationOptions = new StackExchange.Redis.ConfigurationOptions()
        {
            EndPoints = { { "192.168.3.28", 6379 } },
            Password = "123456"
        };
        options.InstanceName = "TestRedisCache";
    });
    services.AddControllers();
}

4.4 第四步:Controller中調用

同分布式內存緩存

附:代碼運行過程中redis存儲數據截圖
在這裏插入圖片描述
從上面的截圖中可以看到,存儲的時候八absexp和sldexp也存儲了進去,也就是一個緩存項被當成一個hash存儲了起來。

五、總結

從上面的介紹中可以看到,雖然我們分別使用了Sqlserver、Redis緩存方式但調用代碼不用做任何改變,而這正是由於我們調用的是IDistributedCache接口提供的服務。

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