【问题标题】:Cache invalidation strategy缓存失效策略
【发布时间】:2015-07-21 21:04:05
【问题描述】:

在我当前的应用程序中,我们正在处理一些很少更改的信息。
为了优化性能,我们希望将它们存储在缓存中
但问题在于每次更新这些对象时都会使这些对象失效
我们还没有最终确定缓存产品。
当我们在 Azure 上构建这个应用程序时,我们可能会使用Azure Redis cache
一种策略是在Update API 中添加代码,这将使缓存中的对象无效。
我不确定这是否是一种干净的方式?
我们不想使用基于时间 (TTL) 的 Cache Expiration
您能否建议一些其他用于缓存失效的策略?

【问题讨论】:

    标签: caching redis


    【解决方案1】:

    更新阶段使缓存失效是一种可行的方法,并且在过去被大量使用。

    当更新发生时,您有两个选择:

    1. 您可以尝试在更新操作期间设置新值,或者
    2. 只需删除旧的在读取操作期间更新

    如果你想要一个 LRU cache,那么 UPDATE 可能只是删除旧值,并且第一次获取对象时,你将在从实际数据库中读取后再次创建它.但是,如果您知道您的缓存非常小,并且您正在使用另一个主数据库来解决与数据大小不同的问题,您可以在 UPDATE 期间直接更新。

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

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

    因此 del-cache-on-update 和 write-cache-on-read 是基本策略,但您可以使用其他附加系统来最终修复不一致。

    其实还有一个选项可以代替上面的选项,那就是有一个后台进程使用RedisSCAN来逐个验证是否有不一致的地方。此过程可能很慢,并且可以针对您的数据库副本运行。

    正如您在此处看到的,主要思想始终是相同的:如果缓存更新失败,不要让它成为可能永远存在的永久性问题,让它有机会在以后自行修复.

    【讨论】:

    • del-cache-on-update 可能会在同时调用 fetch 操作并且值不在缓存中时导致踩踏,所有请求都将转到数据库。可以避免使用锁定或其他策略。因此,在读取期间更新缓存可能是更好的选择。
    【解决方案2】:

    我认为 lambda(ish) 架构适用于您的用例。

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

    对于实时更新,您必须使用应用程序的代码库将数据写入数据库和缓存。

    对于批量数据加载,您可以查看数据提取工具(例如 logstash/fluentd),以从数据库中“提取”最新数据并将其推送到缓存中。这可以基于始终递增的列(ID 号或时间戳)来完成。

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

    【讨论】:

      猜你喜欢
      • 2011-06-27
      • 2022-08-08
      • 2010-10-06
      • 1970-01-01
      • 2012-09-05
      • 2020-08-03
      • 2011-11-12
      • 2011-01-18
      • 1970-01-01
      相关资源
      最近更新 更多