我正在考虑在Web服务器中缓存动态内容。我的目标是通过返回缓存的HTTP响应来桥接整个处理,而不会打扰DB(或Hibernate)。这个问题不是在现有的缓存解决方案之间进行选择;我目前关注的是失效。
我确定,基于时间的失效根本没有意义:每当用户改变任何东西时,他们都希望立即看到效果,而不是几秒甚至几分钟。缓存几分之一秒是没用的,因为在如此短的时间内没有重复请求相同的数据(因为大多数数据都是用户特定的)。
对于每次数据更改,我都会收到一个事件,可以根据更改的数据使用它来使一切无效。当请求同时发生时,有两个与时间相关的问题:
这两个问题彼此相反。我想,通过使用每个客户端ReadWriteLock
部分序列化来自同一客户端的请求,可以轻松解决前者问题。所以,让我们忘记吧。
后者更严重,因为它基本上意味着失去失效并永远(或太长)提供陈旧数据。
我可以想象一个解决方案,比如在变更发生之前每个请求开始后重复失效,但这听起来相当复杂和耗时。我想知道是否有任何现有的缓存支持这一点,但我主要对如何完成这一操作感兴趣。
问题是一个简单的竞争条件:
答案 0 :(得分:2)
要解决争用条件,请添加时间戳(或计数器)并在设置新缓存条目时检查此时间戳。 这可确保不会缓存过时的响应。
这是一个伪代码:
//set new cache entry if resourceId is not cached
//or if existing entry is stale
function setCache(resourceId, requestTimestamp, responseData) {
if (cache[resourceId]) {
if (cache[resourceId].timestamp > requestTimestamp) {
//existing entry is newer
return;
} else
if (cache[resourceId].timestamp = requestTimestamp) {
//ensure invalidation
responseData = null;
}
}
cache[resourceId] = {
timestamp: requestTimestamp,
response: responseData
};
}
假设我们收到2个相同资源“foo”的请求:
setCache("foo", "00:00:00.001", null)
setCache("foo", "00:00:00.000", ...)
将过时的响应写入缓存但由于现有条目较新而失败这只是基本机制,所以还有改进的余地。
答案 1 :(得分:1)
我认为你没有意识到(或者不想明确地呼唤)你在询问缓存同步策略之间的选择。有几个众所周知的策略:"缓存旁边","通读","通过"和#34;写后面"。例如在这里阅读:A beginner’s guide to Cache synchronization strategies。它们提供各种级别的缓存一致性(在您调用时失效)。
您的选择应取决于您的需求和要求。
听起来你已经选择了"写在后面"策略(队列或延迟缓存失效)。但是从您的担忧中听起来您已经错误地选择了它,因为您担心缓存读取不一致。
所以,你应该考虑使用"缓存而不是#34;或"读/写通过"策略,因为那些提供更好的缓存一致性。它们都是同一个东西的不同风格 - 始终保持缓存一致。如果你不关心缓存的一致性,那么好吧,继续"写下",然后这个问题变得无关紧要。
体系结构广泛,我永远不会提高事件来使缓存失效,因为您似乎已将其作为业务逻辑的一部分,而它只是一个基础架构问题。作为读/写操作的一部分而不是高速缓存(或队列失效),而不是其他地方。这使缓存成为您基础架构的一个方面,而不是其他任何方面。