.NET 缓存:内存缓存 IMemoryCache、分布式缓存 IDistributedCache(Redis)

.NET缓存里分了几类,主要学习内存缓存、分布式缓存

一、内存缓存 IMemoryCache

1、Program注入缓存
C# 复制代码
builder.Services.AddMemoryCache();
2、相关方法及参数

Get、TryGetValue、GetOrCreate、GetOrCreateAsync、Set、Remove,关键参数是过期时间,GetOrCreate、GetOrCreateAsync是通过委托类型的参数设置的,Set方法可以通过参数直接设置,或者使用MemoryCacheEntryOptions,类型有三种:
(1)AbsoluteExpiration 绝对过期,到期删除
(2)AbsoluteExpirationRelativeToNow 相对当前时间过期,到期删除
(3)SlidingExpiration 滑动过期,时效内访问再延长,未访问到期删除

C# 复制代码
[Route("api/[controller]/[action]")]
[ApiController]
public class MemoryCacheController : ControllerBase
{
    private readonly IMemoryCache _memoryCache;
    private readonly string cacheKey = "cache";
    public MemoryCacheController(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }

    [HttpGet]
    public string Get()
    {
        var value = _memoryCache.Get(cacheKey);
        return value == null ? "null" : value.ToString();
    }

    [HttpGet]
    public string TryGetValue()
    {
        if (_memoryCache.TryGetValue(cacheKey, out string value))
            return value;
        return "null";
    }

    [HttpGet]
    public string GetOrCreate()
    {
        var value = _memoryCache.GetOrCreate(
            cacheKey,
            cacheEntry =>
             {
                 cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(3);
                 return "GetOrCreate:" + DateTime.Now.ToString("T");
             });
        return value;
    }

    [HttpGet]
    public async Task<string> GetOrCreateAsync()
    {
        var value = await _memoryCache.GetOrCreateAsync(
            cacheKey,
            cacheEntry =>
            {
                cacheEntry.SlidingExpiration = TimeSpan.FromSeconds(3);
                return Task.FromResult("GetOrCreateAsync:" + DateTime.Now.ToString("T"));
            });
        return value;
    }

    [HttpPost]
    public void Set()
    {
        string value = "Set:" + DateTime.Now.ToString("T");

        MemoryCacheEntryOptions op = new MemoryCacheEntryOptions();

        //绝对到期,到期删除
        op.AbsoluteExpiration = DateTimeOffset.Parse("2023-12-31 23:59:59");
        //_memoryCache.Set(cacheKey, value, DateTimeOffset.Parse("2023-12-31 23:59:59"));

        //相对当前时间过期,到期删除
        op.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);
        //_memoryCache.Set(cacheKey, value, TimeSpan.FromSeconds(10));

        //滑动过期,时效内访问再延长,未访问到期删除
        op.SlidingExpiration = TimeSpan.FromSeconds(10);

        _memoryCache.Set(cacheKey, value, op);
    }

    [HttpDelete]
    public void Remove()
    {
        _memoryCache.Remove(cacheKey);
    }
}

二、分布式缓存 IDistributedCache

工欲善其事,必先利其器------>Redis安装

1、Program注入缓存

(1)先安装Nuget:Microsoft.Extensions.Caching.StackExchangeRedis
(2)appsettings.json配置Redis连接

C# 复制代码
"Redis": "39.107.109.17:6379,password=shenhuak1"

(3)Program注入

C# 复制代码
//Redis分布式缓存
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration["Redis"];
    options.InstanceName = "RedisInstance";//实例名,配置后实际的key=InstanceName+key
});
2、相关方法及参数

IDistributedCache 接口提供方法:Get、GetAsync、Set、SetAsync、Refresh、RefreshAsync、Remove、RemoveAsync
以及拓展方法:GetString、GetStringAsync、SetString、SetStringAsync
过期参数跟内存缓存差不多,直接看代码

C# 复制代码
[Route("api/[controller]/[action]")]
[ApiController]
public class DistributedController : ControllerBase
{
    private readonly IDistributedCache _distributedCache;
    private readonly string cacheKey = "cache";
    public DistributedController(IDistributedCache distributedCache)
    {
        _distributedCache = distributedCache;
    }

    [HttpGet]
    public string Get()
    {
        return _distributedCache.GetString(cacheKey);
    }

    [HttpGet]
    public async Task<string> GetAsync()
    {
        return await _distributedCache.GetStringAsync(cacheKey);
    }

    [HttpPost]
    public void Set()
    {
        DistributedCacheEntryOptions op = new DistributedCacheEntryOptions();

        //绝对过期,到期删除
        op.AbsoluteExpiration = DateTimeOffset.Parse("2023-12-31 23:59:59");//op.SetAbsoluteExpiration(DateTimeOffset.Parse("2023-12-31 23:59:59"));

        //相对当前时间过期,到期删除
        op.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);//op.SetAbsoluteExpiration(TimeSpan.FromSeconds(10));

        //滑动过期,时效内访问再延长,未访问到期删除
        op.SlidingExpiration = TimeSpan.FromSeconds(10);//op.SetSlidingExpiration(TimeSpan.FromSeconds(10));

        _distributedCache.SetString(cacheKey, DateTime.Now.ToString("T"), op);
    }

    [HttpPost]
    public async Task SetAsync()
    {
        await _distributedCache.SetStringAsync(cacheKey, DateTime.Now.ToString("T"));
    }

    [HttpPost]
    public void Refresh()
    {
        _distributedCache.Refresh(cacheKey);
    }

    [HttpPost]
    public async Task RefreshAsync()
    {
        await _distributedCache.RefreshAsync(cacheKey);
    }

    [HttpDelete]
    public void Remove()
    {
        _distributedCache.Remove(cacheKey);
    }

    [HttpDelete]
    public async void RemoveAsync()
    {
        await _distributedCache.RemoveAsync(cacheKey);
    }
}
3、总结

非拓展方法是都是通过byte[]字节数组来向Redis存取数据的不方便,大多情况都会自己封装一个helper类。拓展方法虽然用string类型操作,实际存储到Redis是用的Hash类型,无法操作Redis其他类型及功能。
完整功能需要使用其他客户端:StackExchange.Redis、FreeRedis、NRedisStack 等