ASP .NET Core DistributedCache缓存
缓存可以通过减少生成内容所需的工作,显著提高应用的性能和可伸缩性。 缓存最适用于不常更改且生成成本很高的数据。 缓存生成的数据副本可以比从源中更快地返回。 应该以从不依赖于缓存数据的方式编写和测试应用。ASP.NET Core 支持多个不同的缓存。
本文主要介绍五种缓存方式
缓存类别 | Nuget |
---|---|
Memory内存 | Microsoft.Extensions.Caching.Memory |
SqlServer | Microsoft.Extensions.Caching.SqlServer |
Redis | Microsoft.Extensions.Caching.StackExchangeRedis |
Mysql | Pomelo.Extensions.Caching.MySql |
PostgreSql | Community.Microsoft.Extensions.Caching.PostgreSql |
第三方缓存帮助包
添加缓存服务
Memory
services.AddDistributedMemoryCache();
Redis
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "192.168.1.105:6379,password=1qaz@WSX3edc$RFV,ssl=False,abortConnect=False,defaultDatabase=2";
options.InstanceName = "App-Instance-Keys";
});
services.AddStackExchangeRedisCache(options =>
{
options.ConfigurationOptions = new StackExchange.Redis.ConfigurationOptions()
{
DefaultDatabase=2,
Password = "1qaz@WSX3edc$RFV",
ConnectTimeout = 5000,//设置建立连接到Redis服务器的超时时间为5000毫秒
SyncTimeout = 5000,//设置对Redis服务器进行同步操作的超时时间为5000毫秒
ResponseTimeout = 5000,//设置对Redis服务器进行操作的响应超时时间为5000毫秒
Ssl = false,//设置启用SSL安全加密传输Redis数据
//SslHost=""
//SslProtocols = System.Security.Authentication.SslProtocols.Tls//还可以通过SslProtocols属性指定SSL具体用到的是什么协议,不过这个属性不是必须的
};
options.ConfigurationOptions.EndPoints.Add("192.168.1.105:6379");
options.InstanceName = "App-Instance-Keys";
});
SqlServer
services.AddDistributedSqlServerCache(options =>
{
options.SchemaName = "dbo";
options.ConnectionString = Configuration["SqlServerConnection"];
//表名
options.TableName = "TestCache";
//默认缓存时间
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(20);
//过时自动删除
options.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(30);
});
命令行创建表
#默认安装最新版
dotnet tool install --global dotnet-sql-cache
#安装指定版本
#dotnet tool install --global dotnet-sql-cache --version 6.0.0
#创建缓存表
dotnet sql-cache create "Data Source=127.0.0.1;Database=Test;Uid=sa;Pwd=123456;" dbo TestCache
出现Table and index were created successfully.
代表创建成功
Sql脚本创建表
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TestCache](
[Id] [nvarchar](449) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL,
[Value] [varbinary](max) NOT NULL,
[ExpiresAtTime] [datetimeoffset](7) NOT NULL,
[SlidingExpirationInSeconds] [bigint] NULL,
[AbsoluteExpiration] [datetimeoffset](7) NULL,
PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [Index_ExpiresAtTime] ON [dbo].[TestCache]
(
[ExpiresAtTime] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
查看缓存表数据SELECT * FROM TestCache
Mysql
services.AddDistributedMySqlCache(options => {
//数据库名称
options.SchemaName = "dbName";
//AllowUserVariables必须加不然会报错
options.ConnectionString = "server=127.0.0.1;uid=root;pwd=123456;database=mysql;port=3306;pooling=false;SslMode=None;old Guids=true;Charset=utf8;AllowUserVariables=true;";
//表名
options.TableName = "testcache";
//默认缓存时间
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(20);
//过时自动删除
options.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(30);
});
命令行创建表
#默认安装最新版
dotnet tool install --global Pomelo.Extensions.Caching.MySqlConfig.Tools
#创建缓存表(mysql是指数据库名称)
dotnet-mysql-cache create "server=127.0.0.1;uid=root;pwd=123456;database=mysql;port=3306;pooling=false;SslMode=None;old Guids=true;Charset=utf8;" mysql TestCache
出现Table and index were created successfully.
代表创建成功
Sql脚本创建表
# DROP TABLE IF EXISTS `testcache`;
CREATE TABLE `testcache` (
`Id` varchar(449) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`AbsoluteExpiration` datetime(6) DEFAULT NULL,
`ExpiresAtTime` datetime(6) NOT NULL,
`SlidingExpirationInSeconds` bigint DEFAULT NULL,
`Value` longblob NOT NULL,
PRIMARY KEY (`Id`),
KEY `Index_ExpiresAtTime` (`ExpiresAtTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
PostgreSql
--using Community.Microsoft.Extensions.Caching.PostgreSql;
services.AddDistributedPostgreSqlCache(options =>
{
options.ConnectionString = "host=127.0.0.1;Port=5432;database=postgres;username=postgres;password=123456;";
//模式
options.SchemaName = "public";
//表名
options.TableName = "tbl_cache";
//默认过期时间
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(20);
//过时自动删除
options.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(5);
});
程序运行后会自动创建模式和表。或者使用Sql脚本手动创建。
使用缓存
DistributedCacheEntryOptions
是设置缓存时间的配置类
//设置十分钟后过期
new DistributedCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(10));
//设置以当前时间为例,十分钟后过期
new DistributedCacheEntryOptions().SetAbsoluteExpiration(DateTimeOffset.Now.AddMinutes(10));
new DistributedCacheEntryOptions {
//设置未来某一个时间过期
AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(10),
//设置以当前时间为例,过过长时间过期,案例为10分钟
//AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
};
设置缓存
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Threading.Tasks;
namespace MicrosoftCache.Controllers
{
[ApiController]
[Route("[controller]")]
public class RedisController : ControllerBase
{
private readonly IDistributedCache _distributedCache;
public RedisController(IDistributedCache distributedCache)
{
_distributedCache = distributedCache;
}
[HttpGet]
public async Task Get()
{
//设置十分钟后过期
var dco= new DistributedCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(10));
string key = "demokey";
//添加/修改缓存时间
_distributedCache.SetString(key, "123456", dco);
//异步缓存
await _distributedCache.SetStringAsync("demokeyAsync", "123456", dco);
//获取缓存数据
var getvlaue = _distributedCache.GetString(key);
//刷新
_distributedCache.Refresh(key);
//删除
_distributedCache.Remove(key);
object value = new { id=1,user = "zs" };
var stringObject = System.Text.Json.JsonSerializer.Serialize(value, new System.Text.Json.JsonSerializerOptions
{
//.Net6+
ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles
});
var bytesObject = System.Text.Encoding.UTF8.GetBytes(stringObject);//将Json字符串通过UTF-8编码,序列化为字节数组
//设置byte 缓存
_distributedCache.Set(key, bytesObject, dco);
//刷新Redis
_distributedCache.Refresh(key);
//获取byte 缓存数据
var bytesGetObject = _distributedCache.Get(key);
var stringGetObject = System.Text.Encoding.UTF8.GetString(bytesGetObject);//通过UTF-8编码,将字节数组反序列化为Json字符串
var bytevlaue = System.Text.Json.JsonSerializer.Deserialize<object>(stringGetObject);
}
}
}
缓存帮助类
using Microsoft.Extensions.Caching.Distributed;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace WebApplication1
{
/// <summary>
/// Cache缓存操作类
/// </summary>
public class CacheHelper
{
protected IDistributedCache cache;
/// <summary>
/// 通过IDistributedCache来构造RedisCache缓存操作类
/// </summary>
/// <param name="cache">IDistributedCache对象</param>
public CacheHelper(IDistributedCache cache)
{
this.cache = cache;
}
/// <summary>
/// 添加或更改Redis的键值,并设置缓存的过期策略
/// </summary>
/// <param name="key">缓存键</param>
/// <param name="value">缓存对象</param>
/// <param name="timeSpan">设置Redis缓存的过期策略</param>
public void Set(string key, object value, TimeSpan timeSpan)
{
string stringObject = JsonSerializer.Serialize(value,
new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles });
Set(key, stringObject, timeSpan);
}
/// <summary>
/// 添加或更改Redis的键值,并设置缓存的过期策略
/// </summary>
/// <param name="key">缓存键</param>
/// <param name="value">缓存string</param>
/// <param name="timeSpan">设置Redis缓存的过期策略</param>
public void SetString(string key, string value, TimeSpan timeSpan) => Set(key, value, timeSpan);
/// <summary>
/// 查询键值是否在Redis中存在
/// </summary>
/// <param name="key">缓存键</param>
/// <returns>true:存在,false:不存在</returns>
public bool Exist(string key) => cache.Get(key) != null;
/// <summary>
/// Redis中删除键值
/// </summary>
/// <param name="key">缓存键</param>
public void Remove(string key) => cache.Remove(key);
/// <summary>
/// Redis中获取键值
/// </summary>
/// <typeparam name="T">缓存的类型</typeparam>
/// <param name="key">缓存键</param>
/// <returns>缓存对象</returns>
public T? Get<T>(string key)
{
var bytesObject = cache.Get(key);
return bytesObject == null ? default(T) : JsonSerializer.Deserialize<T>(Encoding.UTF8.GetString(bytesObject));
}
/// <summary>
/// Redis中获取键值
/// </summary>
/// <typeparam name="T">缓存的类型</typeparam>
/// <param name="key">缓存键</param>
/// <returns>缓存String</returns>
public string? GetString(string key)
{
var bytesObject = cache.Get(key);
return bytesObject == null ? null : Encoding.UTF8.GetString(bytesObject);
}
/// <summary>
/// 添加或更改Redis的键值,并设置缓存的过期策略
/// </summary>
/// <param name="key">缓存键</param>
/// <param name="value">缓存值一般是对象</param>
/// <param name="timeSpan">设置Redis缓存的过期策略</param>
private void Set(string key, string value, TimeSpan timeSpan)
{
var distributedCacheEntryOptions = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = timeSpan };
cache.Set(key, Encoding.UTF8.GetBytes(value), distributedCacheEntryOptions);
cache.Refresh(key);//刷新Redis
}
}
}