Caching 缓存失效算法
我正在考虑在web服务器中缓存动态内容。我的目标是通过返回缓存的HTTP响应来桥接整个处理过程,而不影响DB(或Hibernate)。这个问题不是关于在现有缓存解决方案之间进行选择;我现在关心的是无效判决 我敢肯定,基于时间的失效是毫无意义的:每当用户更改任何内容时,他们都希望立即看到效果,而不是几秒钟甚至几分钟。而缓存几秒钟是没有用的,因为在如此短的时间内不会重复请求相同的数据(因为大多数数据都是特定于用户的) 对于每一次数据更改,我都会得到一个事件,并可以使用它根据更改的数据使所有内容无效。由于请求同时发生,因此存在两个与时间相关的问题:Caching 缓存失效算法,caching,invalidation,Caching,Invalidation,我正在考虑在web服务器中缓存动态内容。我的目标是通过返回缓存的HTTP响应来桥接整个处理过程,而不影响DB(或Hibernate)。这个问题不是关于在现有缓存解决方案之间进行选择;我现在关心的是无效判决 我敢肯定,基于时间的失效是毫无意义的:每当用户更改任何内容时,他们都希望立即看到效果,而不是几秒钟甚至几分钟。而缓存几秒钟是没有用的,因为在如此短的时间内不会重复请求相同的数据(因为大多数数据都是特定于用户的) 对于每一次数据更改,我都会得到一个事件,并可以使用它根据更改的数据使所有内容无效。
- 失效可能来得太迟,过时的数据甚至可能被提供给更改数据的客户
- 失效结束后,长时间运行的请求可能会结束,其过时数据可能会被放入缓存
ReadWriteLock
部分序列化来自同一客户机的请求,可以很容易地解决前者。所以,让我们忘掉它吧
后者更为严重,因为它基本上意味着失效丢失,并永远(或太长时间)服务陈旧数据
我可以想象一个解决方案,比如在更改发生之前,在每个请求启动后重复失效,但这听起来相当复杂和耗时。我想知道是否有任何现有的缓存支持这一点,但我主要感兴趣的是如何实现这一点
澄清
问题在于一个简单的竞争条件:
- 请求A执行查询并获取结果
- 请求B做了一些更改
- 由于B发生失效
- 请求A(由于任何原因延迟)完成
- 请求A的过时响应被写入缓存
//如果未缓存resourceId,则设置新的缓存项
//或者如果现有条目已过时
函数setCache(resourceId、requestTimestamp、responseData){
if(缓存[resourceId]){
if(缓存[resourceId].timestamp>requestTimestamp){
//现有条目较新
返回;
}否则
if(缓存[resourceId].timestamp=requestTimestamp){
//确保无效
responseData=null;
}
}
缓存[resourceId]={
时间戳:请求时间戳,
答复:答复数据
};
}
假设我们收到了两个对同一资源“foo”的请求:
- 请求A(在00:00:00.000收到)执行查询并获取结果
- 请求B(在00:00:00.001收到)进行了一些更改
- 由于B而导致的失效是通过调用
setCache(“foo”,“00:00:00.001”,null)
- 请求完成
- 请求A调用setCache(“foo”、“00:00:00.000”和…)将过时响应写入缓存,但由于现有条目较新而失败
在整个体系结构范围内,我永远不会去引发事件来使缓存失效,因为看起来您已经将其作为业务逻辑的一部分,而它只是一个基础架构问题。将缓存失效(或队列失效)作为读/写操作的一部分,而不是在其他地方。这使得缓存只成为基础设施的一个方面,而不是所有其他方面。缓存系统将与应用程序集成还是单独集成?@Rei它将根据需要紧密集成。我不知道一般情况下是如何实现的,但当我需要集成缓存系统时,我四处寻找现有的解决方案,发现只有基于时间的缓存。我决定写我自己的,结果比我预期的要简单,而且肯定更有效,因为它没有你已经发现的基于时间的问题。数据更改事件是关键。@Rei这就是我要尝试的。我当前的问题是数据更改事件和延迟响应之间的竞争条件;我刚刚补充了一个说明。这听起来很简单,也很简单,我确信,我已经试过了。。。。但我想不起来是什么让我拒绝了(一周对我糟糕的记忆来说可能太多了)。现在,我相信,它应该会起作用。这也发生在我身上,这就是为什么我必须强迫自己评论我的代码。我并不总是成功,因为写代码比写评论有趣得多。:-)同时我已经把它修好了。。。使用失效的起始日期并保留无效的ent