3 个版本
| 0.1.2 | 2023年10月19日 | 
|---|---|
| 0.1.1 | 2023年10月17日 | 
| 0.1.0 | 2023年10月17日 | 
#111 in 缓存
64KB
 1.5K  SLoC
renege
使用快速并发失效传播跟踪缓存有效性。
背景
每当计算机程序需要多次使用相同的数据或计算时,最简单、最易优化的方法通常是缓存它。然而,这引入了一个众所周知的棘手问题:防止过时数据。缓存的有效性取决于一系列 条件。这些是在缓存被填充时为真,并且在构建缓存时假设为真的陈述,但未来不一定为真。例如
- 数据库的最后修改是在 2023-10-17T20:03:38
- 用户有 view权限
- 文件 config.yaml由特定的字符串组成
- 模拟材料的杨氏模量为 200 GPa
如果缓存依赖于不再为真的条件,则缓存是 无效的。使用无效缓存中的数据可能会得到与直接检索/计算数据不同的结果,从而使优化无效。
解决此问题的一般方法分为两大类
- 
基于拉取的:当访问缓存时,请求者重新检查缓存依赖的所有条件。如果有任何条件为假,则缓存无效。 - 
优点:简单且易于实现 
- 
缺点:通常较慢,尤其是在有很多条件且/或检查成本较高的情况下。检查的性能惩罚可能会超过缓存的好处 
 
- 
- 
基于推送的:当条件变为假时,依赖于它的缓存被标记为无效。 - 
优点:非常快。当访问缓存时,请求者只需检查它是否被标记为无效 
- 
缺点:难以实现。需要主动监视条件,并跟踪依赖于它们的缓存。当缓存依赖于其他缓存时,需要跟踪整个依赖图,以实现有效的失效。 
 
- 
我们的方法
Renegade 通过为您处理所有跟踪和记录工作,简化了基于推送的缓存失效的实现。API非常简单
Condition: 一个缓存可以依赖的条件。在释放时自动失效。
Token: 跟踪一组任意条件的有效性。
use renege::{Condition, Token};
// Create conditions
let pigs_cant_fly = Condition::new();
let water_is_wet = Condition::new();
// Use .token() to create a Token which tracks the validity of a single Condition
// Tokens can be combined using the & operator
let normality = pigs_cant_fly.token() & water_is_wet.token();
assert!(normality.is_valid());
// Conditions are invalidated when dropped
drop(water_is_wet);
// Use .is_valid() to check if all of the Conditions a Token depends on are still valid
assert!(!normality.is_valid());