在上一篇 拥抱. NET Core 系列: MemoryCache 缓存过期 中我们详细的了解了缓存过期相关的内容, 今天我们来介绍一下 MSCache 中的 Options, 由此来介绍一些 MSCache 中的内部机制
MSCache 项目
MSCache 目前最新的正式版是 2.0.0, 预览版是 2.1.0, 会与 .NETCore 2.1 一起发布本篇用了 2.0.0 版本
开源在 GitHub 上, 仓库地址是: https://github.com/aspnet/Caching
NuGet 地址为: https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/2.0.0
MemoryCacheOptions
Clock 顾名思义, 是用来提供时间的一个成员, 缓存里面大量用到了时间来判断缓存是否过期
CompactOnMemoryPressure 已经被废弃, 可以不用管
ExpirationScanFrequency 过期扫描频率 (默认为 1 分钟, 可以理解为每过多久移除一次过期的缓存项)
SizeLimit 缓存大小限制 (这属于一个说明性属性, 而且单位也不是缓存数目, 而是缓存真正占用的空间大小)
CompactionPercentage 压缩率 (默认 0.05, 百分比)
Clock
初次见到的时候以为是用来自定义 LocalTime, 其实不是 (当然要这么做也可以), 在 MSCache 中只允许用 Utc 时间, 但是为什么既然都是 Utc 时间还要留这个扩展选项呢?
很简单, 默认的当前时间是当前系统的当前时间, 在一些对时间精度要求比较高的情况下就可以重写 Clock 来实现自己自定义的获取当前时间的逻辑
ExpirationScanFrequency
缓存无非是一个字典表, 当一些缓存项过期失效时候我们需要移除字典表里面的内容
然而准确的做到每个缓冲项过期就进行移除是非常损失性能的 (类似 GC), 所以 MSCache 提供了一个属性来设置, 没间隔多久才进行一次过期缓存移除
这个值默认为 1 分钟
什么时候会进行过期缓存清理?
添加新的
获取缓存项
删除缓存项目
当有缓存项过期 (通过过期回调)
这边就解释了上一节的最后为什么没有回调输出
因为 MSCache 里面没有使用定时器来进行过期扫描
ps: 缓存过期清理是一个异步方法也就是不会堵塞当前线程
SizeLimit
这个属性在 MemoryCache 中几乎没有用, 在 MemoryCache 中关于缓存项的大小默认都是 null 或 0
因为这个属性并不是缓存项的数量, 而是缓存真正占用的空间大小, 如这个缓存项占用了多少内存
然而在. NET 中计算一个对象所占用的内存是很难且损耗性能的, 所以在 MemoryCache 中这个属性几乎可以看做没有
当然你可以通过手动设置缓存项的 Size 来启用相关功能这边我们只简单说明, 详细讲解会在后面的分布式缓存中进行说明
这个属性的作用是: 当所有缓存大小超过这个值的时候进行一次缓存压缩
CompactionPercentage
当内存大小超过 SizeLimit 时候进行压缩的比率, 默认值是 0.05, 也就是百分之 5
具体的计算方式是
得到剩余的缓存大小 SizeLimit * 1 CompactionPercentage
得到需要压缩的大小 CurrentSize (SizeLimit * 1 CompactionPercentage)
缓存的清理优先级
这时候就牵扯到 CacheEntry 中的 Priority 属性了, 当发生这种情况的时候 MSCache 会按以下优先级进行压缩处理
Low
Normal
High
为什么没有 NeverRemove ? 因为 NeverRemove 永远不会在超过 SizeLimt 时候进行清理
那么当缓存大小超过 SizeLimit 时, MSCache 会
先清理 Low 优先级的缓存项 (不管是否过期)
再清理 Normal 优先级的缓存项 (不管是否过期)
继续清理 High 优先级的缓存项 (不管是否过期)
CacheEntry 默认的 优先级为: Normal
写在最后
今天介绍了一些 MSCache 的内部机制, 后续会讲一下 缓存域 和 一些小技巧
.NET 技术栈 QQ 群: 384413261(点击加入 .NET Group)
来源: https://www.cnblogs.com/ants/p/8526935.html