缓存失效策略

时间:2015-05-11 11:19:07

标签: caching redis

在我目前的申请中,我们正在处理一些很少改变的信息。对于性能优化,我们希望将它们存储在缓存中。但问题是在更新这些对象时无效。我们还没有最终确定缓存产品。当我们在Azure上构建此应用程序时,我们可能会使用' Azure redis缓存'。一种策略可能是在“更新API”中添加代码。这将使缓存中的对象无效。我不确定这是否干净。我们不希望根据时间使用缓存过期。你能否建议一些其他用于缓存失效的策略?

3 个答案:

答案 0 :(得分:18)

更新阶段使缓存无效是一种可行的方法,并且在过去非常常用。这里有两个选项:您可以尝试在UPDATE发生时设置新值,或者只删除旧值并在读取操作期间更新。如果你想要一个LRU缓存,那么UPDATE可能只是删除旧值,并且第一次获取对象时,你将在从实际数据库读取后再次创建它。但是,如果您知道缓存非常小并且您正在使用另一个主数据库来处理与数据大小不同的问题,则可以在UPDATE期间直接更新。

然而,这一切还不足以完全一致。当您写入数据库时​​,Redis缓存可能会在几秒钟内不可用,因此数据在两者之间保持不同步。你在那种情况下做了什么?您可以同时使用多种选项。

  1. 无论如何设置一个TTL,以便最终刷新数据。
  2. 使用延迟读取修复。当您从数据库中读取数据时,如果值匹配,则不时检查主数据库。如果不更新缓存的项目(或删除它)。
  3. 使用纪元或类似方式访问您的数据。并非总是可行,但有时您会访问有关给定对象的缓存数据。如果可能,您可以在每次修改时更改对象ID /句柄,这样就无法访问缓存中的陈旧数据:每个键名都指对象的特定版本。 / LI>

    所以del-cache-on-update和write-cache-on-read是基本策略,但你可以使用其他额外的系统来最终修复不一致。

    实际上还有另一个选项,而不是使用上面的选项,即如果存在不一致,则使用Redis SCAN进行后台处理以按键验证密钥。此过程可能很慢,可以针对数据库的副本运行。

    正如你在这里看到的那样,主要思想总是一样的:如果对缓存的更新失败,请不要将其永久保留在那里,让它有机会在以后修复自己

答案 1 :(得分:0)

我认为lambda(ish)体系结构适用于您的用例。

  1. 实时更新以立即用于业务
  2. 批处理数据加载以修复任何失败的记录
  3. 批处理数据加载以删除无效/存档记录中的任何记录。

对于实时更新,您将必须在应用程序的代码库上进行工作,才能将数据写入数据库和缓存。

对于批量数据加载,您可以查看数据提取工具,例如logstash / fluentd,以从数据库中“抽取”最新数据。可以根据始终递增的列(ID号或时间戳)来完成此操作。

我最后有Oracle数据库。 Logstash JDBC插件在提取最新记录方面做得不错。 logstash输出可以格式化并打印到Redis可以使用的文件中。我写了一个小的bash脚本来对此进行编排。测试了300万条记录并可以正常工作。

答案 2 :(得分:-2)

除了TTL(生存时间,例如在给定时间段后删除密钥),通常的策略是LRU(最近最少使用):当您需要删除某些条目时(例如,当您达到最大内存限制时) ,删除最旧的条目。

但是,要确切知道哪个条目是最早的条目很长,所以Redis使用统计方法,只需要几个(默认为3个)条目,并删除最近最少使用的条目。

请参阅http://redis.io/topics/lru-cache

相关问题