欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

.netcore入门18:aspnetcore分布式缓存(分布式内存、sqlserver、redis)

程序员文章站 2022-03-30 10:43:16
...

环境:

  • 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();
        }
    }
}

上面代码的控制台输出如下图:
.netcore入门18:aspnetcore分布式缓存(分布式内存、sqlserver、redis)

三、分布式SqlServer缓存

aspnetcore框架提供的这个实现可以让我们很方便的把sqlserver当成一个缓存容器,它的源码也很简单,就是对一张缓存表的增删改查。我们看一下它的源码文件:
.netcore入门18:aspnetcore分布式缓存(分布式内存、sqlserver、redis)
有兴趣的可以点开看看里面的内容,里面操作数据库没有依赖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包引入进来:
.netcore入门18:aspnetcore分布式缓存(分布式内存、sqlserver、redis)

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数据库中存储的情况:
.netcore入门18:aspnetcore分布式缓存(分布式内存、sqlserver、redis)

四、分布式Redis缓存

redis服务器搭建参考:redis入门(1): linux下安装redis与简单配置
redis客户端下载地址:
链接:https://pan.baidu.com/s/1l2NPkhgVdnEM89vpJIwGfA
提取码:beg4
说明:
aspnetcore中分布式Redis缓存的源码很简单,因为它对redis的操作依赖于StackExchange.Redis,先来看看它的源码文件有哪些:
.netcore入门18:aspnetcore分布式缓存(分布式内存、sqlserver、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框架里面,所以需要我们手动添加上去:
.netcore入门18:aspnetcore分布式缓存(分布式内存、sqlserver、redis)

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存储数据截图
.netcore入门18:aspnetcore分布式缓存(分布式内存、sqlserver、redis)
从上面的截图中可以看到,存储的时候八absexp和sldexp也存储了进去,也就是一个缓存项被当成一个hash存储了起来。

五、总结

从上面的介绍中可以看到,虽然我们分别使用了Sqlserver、Redis缓存方式但调用代码不用做任何改变,而这正是由于我们调用的是IDistributedCache接口提供的服务。

相关标签: .netcore

上一篇: 下标和切片

下一篇: Linux内核