.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接口提供的服务。

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