在上一篇拥抱. NET Core 系列: MemoryCache 初识中我们基本了解了缓存的添加删除获取, 那么今天我们来看看缓存的过期机制这里和上篇一样将把 Microsoft.Extensions.Caching.Memory 简称为 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
MSCache 提供的过期方式
从源码来说, MSCache 提供了以下三种缓存过期的方式
绝对到期 (指定在一个固定的时间点到期)
滑动到期 (在一个时间长度内没有被命中则过期)
到期 Token(自定义过期)
下面我们来一一看看这些方式
绝对时间到期
绝对到期非常的简单, MS 提供了一个扩展方法 SetAbsoluteExpiration 用来设置绝对到期时间
这边的第一个方法定义中的 relative 是指从当前时间度过这么久的时间之后过期, 类似 DateTime.Now.Add(relative)
为什么说类似呢?
因为每个国家地区的时间可能不一致, MSCache 默认使用了 UTC 时间, 这个时间可以在 options 进行修改, 后面在做介绍
滑动时间到期
除了前两次迭代满足 2 秒内命中缓存, 剩余的 3 次迭代无法满足 2 秒内命中, 所以从第三次迭代开始缓存项都会过期
自定义过期策略
很多时候我们的缓存过期条件并不是只有时间, 比如我们对一个文件内容进行了缓存, 当文件变动的时候需要重新加载文件更新缓存再比如我们缓存了用户信息, 在一个 bus 上接收到了用户信息变动后清除用户缓存并重新缓存用户
MS 为我们提供了一个非常简单的自定义过期策略
MS 把这个过期策略使用一个接口 IChangeToken 来暴露下面我们来看看 IChangeToken
IChangeToken
IChangeToken 不完全为 MS 而生, 而是一个基础包里面的接口, 所以在理解这个接口的时候尽量不要带入缓存来考虑
HasChanged 顾名思义, 用来返回是否发生了变更, 在 MSCache 中如果返回了 true 则缓存项将会失效
ActiveChangeCallbacks 一个有点玄学的属性, 该属性更多是一种描述, 字面意思是该 token 是否会激活回调, 取决于 IChangeToken 实现者的逻辑, 如果这个值返回 false 则不要期望通过 IChangeToken 的 RegisterChangeCallback 来达到发生变更的时候有回调通知
RegisterChangeCallback 注册一个回调, 当变更发生时执行, 一般配合 ActiveChangeCallbacks 来达成
一个约束并不是强制
ActiveChangeCallbacks 为 true 时通过 RegisterChangeCallback 注册的回调会在发生变更时被回调执行, 反之相反
MS 其它组件实现的 IChangeToken
CancellationChangeToken (一个对 CancellationToken 的包装)
CompositeChangeToken (组合 ChangeToken, 可以将多个 ChangeToken 包装成一个 Token)
ConfigurationReloadToken (配置重新加载 Token, 来自 MS.Configuration 组件)
PollingFileChangeToken (通过轮训来监控文件变更)
PollingWildCardChangeToken (通过轮训来监控文件变更, 这个是支持通配符的)
缓存一个文件, 并在文件变化时候更新缓存内容
手动过期缓存
ChangeToken 的一次性
恩, 妥妥的输出 1 1 2 2?
实际输出结果 1 1 2 3
为什么?
因为我们之前讲到 ChangeToken 是通过 HasChanged 来判断缓存是否过期的
在这边我们调用了 cts 的 Cancel, 那么无论如何 HasChanged 后续都会是 true, 因为 cts 的 Cancel 是不可逆的
正确的做法
这边正确的做法只是强调, ChangeToken 是一次性的, 具体如何达到这个目的大家可以自由发挥
自定义一个 ChangeToken, 当当前时间的分数为偶数时候过期
过期策略组合拳
上面介绍了 MSCache 中的过期策略, 但都是单独使用的, 其实这些过期策略可以混合使用
比如指定 1 个小时后到期或者 10 分钟内没有命中到期
IChangeToken 当然也是可以的
这边的过期策略是只要启动一个条件达成那么这个缓存就是无效的
缓存过期回调
很多时候我们希望缓存过期之后能做一些事情, 比如重新写入缓存等等, MSCache 提供了这样的机制
使用回调相关的定义
示例
写在最后
大家思考一下这段代码为什么会没有回调输出?
来源: https://www.cnblogs.com/ants/p/8482227.html