说到内存缓存MemoryCache不由的让我想起.Net Framework中的MemoryCache,它位于 System.Runtime.Caching 程序集中。
接下来我们来看看.net core中的MemoryCache又有什么与众不同的地方吧。
一、基本实现
1、打开NuGet包管理器搜索并安装 Microsoft.Extensions.Caching.Memory 包,或者从程序包管理控制台执行 Install-Package Microsoft.Extensions.Caching.Memory 命令
2、接下来看实现代码
static void Main(string[] args)
{
MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());
memoryCache.Set("name","tom");
var value = memoryCache.Get("name");
Console.WriteLine(value); Console.ReadKey();
}
结果如下:
二、缓存容量控制:SizeLimit
1、当你用SizeLimit属性设置了这个缓存大小之后,你就必须为你缓存中的每一项设置大小,否则则报错。当然,当你的大小达到你设置的SizeLimit时,你再设置缓存,它会自动清理一些缓存再缓存你设置的值
2、代码如下:
static void Main(string[] args)
{
MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()
{
SizeLimit =
});
for (int i = ; i < 1000; i++)
{
memoryCache.Set<int>(i.ToString(), i, new MemoryCacheEntryOptions() {
Size =
});
}
Console.WriteLine(memoryCache.Count); Console.ReadKey();
}
结果如下:
实际结果不是1000,而是100
我们来看看它设置值的过程是什么样的:
由于设置的大小为100,达到100时再设置缓存项就会自动清理掉一部分
三、缓期的过期问题
1、被动过期
代码如下:
static void Main(string[] args)
{
MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());
memoryCache.Set("name", "jack", new MemoryCacheEntryOptions()
{
AbsoluteExpiration = DateTimeOffset.Now.AddSeconds()//设置为5秒后过期
});
while (true)
{
System.Threading.Thread.Sleep();
string value;
if (!memoryCache.TryGetValue("name", out value))
{
value = "已过期";
}
Console.WriteLine(value);
}
//Console.ReadKey();
}
结果如下:
2、主动过期
static void Main(string[] args)
{
MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); CancellationTokenSource tokenSource = new CancellationTokenSource();
var cacheOptins = new MemoryCacheEntryOptions()
{
AbsoluteExpiration = DateTimeOffset.Now.AddSeconds()//设置为10秒后过期
};
cacheOptins.AddExpirationToken(new CancellationChangeToken(tokenSource.Token)); memoryCache.Set("name", "jack", cacheOptins); tokenSource.CancelAfter();//主动设置为2秒过期
while (true)
{
Thread.Sleep();
string value;
if (!memoryCache.TryGetValue("name", out value))
{
value = "已过期";
}
Console.WriteLine(value);
}
//Console.ReadKey();
}
结果如下:
3、过期后回调:
static void Main(string[] args)
{
MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); CancellationTokenSource tokenSource = new CancellationTokenSource();
var cacheOptins = new MemoryCacheEntryOptions()
{
AbsoluteExpiration = DateTimeOffset.Now.AddSeconds()//设置为10秒后过期
};
cacheOptins.AddExpirationToken(new CancellationChangeToken(tokenSource.Token)); cacheOptins.RegisterPostEvictionCallback((key, value, reason, state) => {
Console.WriteLine(reason);
}); memoryCache.Set("name", "jack", cacheOptins); tokenSource.CancelAfter();//主动设置为2秒过期
while (true)
{
Thread.Sleep();
string value;
if (!memoryCache.TryGetValue("name", out value))
{
value = "已过期";
}
Console.WriteLine(value);
}
//Console.ReadKey();
}
结果如下:
四、其它的一些设置
1、原子性操作
memoryCache.GetOrCreate("name", entry => "lucy");
2、优先级设置,这个设置是为了配合压缩缓存的
以下是系统定义的优先级的枚举
public enum CacheItemPriority
{
Low = ,
Normal = ,
High = ,
NeverRemove =
}
接下来设定优先级
var cacheOptins = new MemoryCacheEntryOptions()
{
Priority= CacheItemPriority.Low,
AbsoluteExpiration = DateTimeOffset.Now.AddSeconds()//设置为10秒后过期
};
3、缓存压缩
static void Main(string[] args)
{
MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()
{
SizeLimit =
});
for (int i = ; i < ; i++)
{
CacheItemPriority priority = CacheItemPriority.Low;
if ( < i && i < )
priority = CacheItemPriority.Normal;
else if ( < i && i < )
priority = CacheItemPriority.High;
else
priority = CacheItemPriority.NeverRemove;
memoryCache.Set(i.ToString(), i.ToString(), new MemoryCacheEntryOptions()
{
Size = ,
Priority = priority,
AbsoluteExpiration = DateTimeOffset.Now.AddSeconds()//设置为10秒后过期
});
}
memoryCache.Compact(0.2);//压缩20%
Console.WriteLine(memoryCache.Count);
for (int i = ; i < ; i++)
{
Console.WriteLine(memoryCache.Get(i.ToString()));
}
Console.ReadKey();
}
结果如下:
压缩后的缓存项数:
被压缩的缓存项:
根据结果可知道,优先级为 CacheItemPriority.Normal 的数据被压缩掉了,由此可见,优先级为 CacheItemPriority.Low 的并没有参加压缩。
压缩的优先级顺序是 CacheItemPriority.Normal>CacheItemPriority.High>CacheItemPriority.NeverRemove