First install the installation package:
Microsoft.Extensions.Caching.Abstractions
Microsoft.Extensions.Caching.Memory
The environment I use is .Net Core3.0
Four strategies for expiration based on time
Let me start with this: Generally, when we use cache, we set expiration strategies based on time. The following four expiration strategies are commonly used:
1.1 永不过期:
1.2 设置绝对过期时间点:
1.3 设置过期滑动窗口:(只要在窗口期内访问,它的过期时间就一直向后顺延一个窗口长度)
1.4 滑动窗口+绝对过期时间点:(只要在窗口期内访问,它的过期时间就一直向后顺延一个窗口长度,但最长不能超过绝对过期时间点)
Four strategy test demos with expiration of test time:
public static IMemoryCache _cache = new MemoryCache(new MemoryCacheOptions());
static async Task Main(string[] args)
{
await Test1();
Console.WriteLine("ok");
Console.ReadLine();
}
/// <summary>
/// 验证滑动窗口+绝对过期时间(这里的绝对过期时间是缓存从开始到结束最长的时间,滑动窗口表示在滑动时间内只要没访问就成立)
/// </summary>
/// <returns></returns>
private async static Task test4()
{
_cache.Set("xdm", "小仙女", new MemoryCacheEntryOptions() {
//滑动窗口 时间15毫秒
SlidingExpiration = TimeSpan.FromSeconds(1.5),
//绝对过期 3.5毫秒
AbsoluteExpiration = DateTime.Now.AddMilliseconds(1000*3.5)
});
await Task.Delay(1000 * 1);
Console.WriteLine("1s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("2s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("3s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("4s" + _cache.Get("xdm"));
await Task.Delay(1000 * 10);
Console.WriteLine("5s" + _cache.Get("xdm"));
}
/// <summary>
/// 验证滑动窗口过期
/// </summary>
/// <returns></returns>
private async static Task Test3()
{
_cache.Set("xdm", "小仙女", new MemoryCacheEntryOptions() {
SlidingExpiration=TimeSpan.FromSeconds(1.5)
});
await Task.Delay(1000 * 1);
Console.WriteLine("1s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("2s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("3s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("4s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("5s" + _cache.Get("xdm"));
}
/// <summary>
/// 验证绝对过期时间
/// </summary>
/// <returns></returns>
private async static Task Test2()
{
_cache.Set("xdm", "小仙女", TimeSpan.FromSeconds(3));
await Task.Delay(1000 * 1);
Console.WriteLine("1s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("2s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("3s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("4s" + _cache.Get("xdm"));
await Task.Delay(1000 * 1);
Console.WriteLine("5s" + _cache.Get("xdm"));
}
/// <summary>
/// 验证永不过期
/// </summary>
/// <returns></returns>
private async static Task Test1()
{
_cache.Set("xdm", "小仙女");
await Task.Delay(1000 * 3);
Console.WriteLine("1s"+_cache.Get("xdm"));
await Task.Delay(1000 * 3);
Console.WriteLine("2s" + _cache.Get("xdm"));
await Task.Delay(1000 * 3);
Console.WriteLine("3s" + _cache.Get("xdm"));
await Task.Delay(1000 * 3);
Console.WriteLine("4s" + _cache.Get("xdm"));
}
Cache helper class
/// <summary>
/// 缓存帮助类
/// </summary>
class CacheManager
{
public static CacheManager Default = new CacheManager();
private IMemoryCache _cache = new MemoryCache(new MemoryCacheOptions());
/// <summary>
/// 取得缓存数据
/// </summary>
/// <typeparam name="T">类型值</typeparam>
/// <param name="key">关键字</param>
/// <returns></returns>
public T Get<T>(string key)
{
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentNullException(nameof(key));
T value;
_cache.TryGetValue<T>(key, out value);
return value;
}
/// <summary>
/// 设置缓存永不过期
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">关键字</param>
/// <param name="value">缓存值</param>
public void Set_NotExpire<T>(string key, T value)
{
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentException(nameof(key));
T v;
if (_cache.TryGetValue(key, out v))
_cache.Remove(key);
_cache.Set(key, value);
}
/// <summary>
/// 设置缓存时间(滑动过期;超过一段时间不访问就会过期,一直访问就一直不过期)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="span"></param>
public void Set_SlidingExpire<T>(string key, T value, TimeSpan span)
{
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentException(nameof(key));
T v;
if (_cache.TryGetValue(key, out v))
_cache.Remove(key);
_cache.Set(key, value, new MemoryCacheEntryOptions()
{
SlidingExpiration = span
});
}
/// <summary>
/// 设置缓存(绝对时间过期:从缓存开始持续指定的时间段后就过期,无论有没有持续的访问)
/// </summary>
/// <param name="key">关键字</param>
/// <param name="value">缓存值</param>
public void Set_AbsoluteExpire<T>(string key, T value, TimeSpan span)
{
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentNullException(nameof(key));
T v;
if (_cache.TryGetValue(key, out v))
_cache.Remove(key);
_cache.Set(key, value, span);
}
/// <summary>
/// 设置缓存(绝对时间过期+滑动过期:比如滑动过期设置半小时,绝对过期时间设置2个小时,那么缓存开始后只要半小时内没有访问就会立马过期,如果半小时内有访问就会向后顺延半小时,但最多只能缓存2个小时)
/// </summary>
/// <param name="key">关键字</param>
/// <param name="value">缓存值</param>
public void Set_SlidingAndAbsoluteExpire<T>(string key, T value, TimeSpan slidingSpan, TimeSpan absoluteSpan)
{
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentNullException(nameof(key));
T v;
if (_cache.TryGetValue(key, out v))
_cache.Remove(key);
_cache.Set(key, value, new MemoryCacheEntryOptions()
{
SlidingExpiration = slidingSpan,
AbsoluteExpiration = DateTimeOffset.Now.AddMilliseconds(absoluteSpan.TotalMilliseconds)
});
}
/// <summary>
/// 移除缓存
/// </summary>
/// <param name="key">关键字</param>
public void Remove(string key)
{
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentNullException(nameof(key));
_cache.Remove(key);
}
/// <summary>
/// 释放
/// </summary>
public void Dispose()
{
if (_cache != null)
_cache.Dispose();
GC.SuppressFinalize(this);
}
}