我正在尝试将Redis用作位于SQL数据库前面的缓存。在高层次上我想实现这些操作:
如果我尝试使用StackExchange.Redis,我的挑战是理解如何实现#1和#3。如果我通过简单的密钥读取和推送来天真地实现#1,那么我之间完全有可能在计算SQL的值并推送它之前可能已经发生了任何其他SQL操作并且还试图推送他们通过#2或#3进入Redis的价值观。例如,请考虑以下顺序:
那么如何实施我的操作#1? Redis提供了一个WATCH
原语,这可以很容易地对付裸机,我可以观察客户端#1上的密钥发生的其他事情,但是it's not supported by StackExchange.Redis because of how it multiplexes commands。它的有条件操作在这里是不够的,因为如果我尝试说"仅当键不存在时才按下#34;这不会阻止比赛,因为我如上所述。这里使用的是模式/最佳实践吗?这似乎是人们想要实现的一种相当普遍的模式。
我有一个想法是我可以使用一个单独的键,每次我对主键执行一些操作时会增加,然后可以使用StackExchange.Redis'有条件的操作,但这看起来很糟糕。
答案 0 :(得分:2)
看起来像关于正确的缓存失效策略的问题,而不是关于Redis的问题。为什么我这么认为 - Redis WATCH / MULTI 是一种乐观锁定策略这种 锁定不适合大多数具有缓存的情况,其中db read query可能是一个解决缓存的问题。在您的操作#3描述中,您写道:
现在重新计算是太多的工作了。我们可以让操作#1的下一个客户再次计算它。
因此,我们可以继续read update
案例作为更新策略。在我们继续之前,还有一些问题:
Optimistic concurrency control假设多个交易可以经常完成而不会相互干扰。在运行时,事务使用数据资源而不获取对这些资源的锁定。在提交之前,每个事务都会验证没有其他事务已修改它已读取的数据。如果检查显示有相互矛盾的修改,则提交事务将回滚并重新启动。
您可以在wikipedia中阅读有关OCC交易阶段的信息,但用几句话来说:
如果没有冲突 - 您更新数据。如果存在冲突,请解决此问题,通常是通过中止事务并在仍需要更新数据时重新启动它。
Redis WATCH / MULTY是一种乐观的锁定,因此他们无法帮助您 - 在尝试使用它们之前,您不知道您的缓存密钥已被修改。
每当你倾听有人讲述锁定时 - 在听完一些话之后你会听到妥协,性能和一致性与可用性。最后一对是最重要的。
在大多数高负载系统中,可用性是赢家。这意味着缓存?通常这样的情况:
如何更新读取(非常重要的是这种“手工制作”乐观和悲观锁定的组合):
如何使(您的操作#2,#3)无效:
对不起,您之前没有说过 - 我不会全部写完。如果队列全部变得更简单:
Actualy是,同时没有。这是一种可能的解决方案。缓存失效是许多可能解决方案的复杂问题 - 其中之一 可能很简单,其他 - 复杂。在大多数情况下,取决于混凝土应用的实际商务要求。