【问题标题】:Possibility of stale data in cache-aside pattern缓存端模式中陈旧数据的可能性
【发布时间】:2017-02-28 19:14:53
【问题描述】:

只是为了重新定义缓存模式,它在获取和更新数据时定义了以下步骤。

获取项目

  1. 如果在缓存中找到,则从缓存中返回该项目。
  2. 如果在缓存中找不到,则从数据存储中读取。
  3. 将读取的项目放入缓存并返回。

更新项目

  1. 将项目写入数据存储区。
  2. 从缓存中删除相应的条目。

这几乎在所有情况下都能完美运行,但在一种理论场景中似乎失败了。

如果更新项目的第 1 步和第 2 步发生在获取项目的第 2 步和第 3 步之间会怎样。换句话说,考虑最初数据存储的值为“A”并且它不在缓存中。因此,在获取项目时,我们从数据存储中读取“A”,但在放入缓存之前,该项目在另一个线程中更新为“B”(因此“B”被写入数据存储并试图从缓存中删除该条目,当时还没有)。现在,当获取线程将它读取的项目(即“A”)放入缓存时。所以现在“A”将保持缓存状态,进一步的提取将返回陈旧的数据,直到项目过期或再次更新。

所以我在这里遗漏了什么,是我对模式的理解是错误的。或者说这种情况几乎是不可能的,不用担心。

我也想知道是否可以对模式进行一些更改以避免这个问题。

【问题讨论】:

    标签: caching design-patterns memcached


    【解决方案1】:

    根据MSDN definition,您对模式的理解似乎完全正确。事实上,它提到了与您描述的相同的失败场景。

    此序列中的步骤顺序很重要。如果在更新缓存之前删除该项目,则客户端应用程序在数据存储中的项目更改之前有一小段机会获取数据(因为在缓存中未找到),从而导致缓存包含过时的数据。

    MSDN 文章确实指出,“期望缓存的数据始终与数据存储中的数据完全一致通常是不切实际的。”过期和逐出是提到的两种处理策略遇到这个问题。

    一个古老的计算机科学joke 是这样的。

    计算机科学中只有两个难题:缓存失效、命名事物和非一错误。

    您偶然发现了这些问题中的第一个。

    【讨论】:

    • 谢谢,我浏览了相同的 MSDN 文章,但我对引用注释的理解是它正在讨论更新项目的步骤(在更新存储之前从缓存中删除的问题)。无论如何,设置较短的到期时间似乎只是一种补救措施,但为了避免理论上的情况,这是一个持续的开销。
    【解决方案2】:

    我也想知道是否可以对模式进行一些更改 避免这个问题。

    一般来说,没有办法避免这种情况。 Memcached 协议引入了一个特殊的命令:

    "cas" is a check and set operation which means "store this data but
      only if no one else has updated since I last fetched it."
    

    场景需要修改:

    获取项目

    1. 如果在缓存中找到,则从缓存中返回该项目。
    2. 如果在缓存中未找到,则从数据存储中读取。
    3. 检查并交换缓存中的相应条目并返回。

    更新项目

    1. 检查并交换缓存中的相应条目。
    2. 将项目写入数据存储区。

    这种情况也不能保证完全一致。

    想象以下情况: 在数据存储中写入项目失败,而在缓存中更新项目成功。最新的项目值将仅保存在缓存中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-20
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-10
      • 1970-01-01
      相关资源
      最近更新 更多