具有GraphQL响应的属性到期的JSON对象缓存

时间:2019-05-15 17:47:17

标签: algorithm caching data-structures hash graphql

我创建了一个缓存(nosql),该缓存使用graphQL json对象并将其扁平化。这意味着所有子对象均被引用替换并单独存储。例如,给出以下输入:

{
    "users": [
         {"type": "user", "id": 1, "name": "bob"}, {"type": "user", "id": 1, "name": "bill"}
    ]
}

它存储为:

{ 
    "users": ["ref-user-1", "ref-user-2"],
    "ref-user-1": {"type": "user", "id": 1, "name": "bob"},
    "ref-user-2": {"type": "user", "id": 1, "name": "bill"}
}

此方法的好处是,如果另一个请求包含user-1上的信息,我们可以更新本地数据存储。然后,如果通过ID向用户提出请求,我们可能会提供所有必需的信息。

问题与缓存失效有关。我们如何知道缓存条目是否最新?为了这篇文章的缘故,我们可以说一个对象是有效的,如果它的所有字段都在2小时内被缓存了。如果user-1提出了另一个请求,我们将为该请求返回的字段更新本地时间戳。

如何以高性能的方式保存每个字段的时间戳?

考虑的选项:

  1. 每个值都有自己的时间戳。所有查找都将是O(1),但我们会有大量重复的时间戳数据。

    "ref-user-1": {"type": "user", "id": {"val": 1, "ts": "1557941674"}, "name": {"val": "bob" "ts": "1557941674"}}

  2. 将属性时间戳存储为属性集,每组单个时间戳。查找会很慢,但是会减少数据。更新也可能非常慢。如果我们可以将字段转换为哈希值,然后检查较大的哈希值是否包含较小哈希值中的所有字段,那就太好了。

    "ref-user-1": {"type": "user", "id": 1, "name": "bob", "field_sets": ["ts": "1557941674", "fields": ["id", "name"]] }

  3. 我没有考虑过的精美数据结构...

1 个答案:

答案 0 :(得分:1)

就像一个古老的笑话所说:“计算机科学中只有两个难题:命名,缓存无效和一个错误。”

所以这是一个很难的问题,应该很困难。

我建议,重要的不是最近返回数据的时间,而是最近缓存数据的时间。否则,通常需要的数据可能会过时并无限期保持。 (看,我说过缓存失效很难!)

这表明时间戳记应基于缓存的最新更新时间。因此,如果数据不到1.5小时,则可以返回该数据。如果时间是1.5-2个小时,您可以掷硬币。 (随着翻转的可能性增加)。如果年龄较大,则将其视为无效。通过这种策略,即使非常活跃地访问数据,刷新数据也可能只请求一次。

此方法需要每个属性的时间戳。并且允许知道它已更改某些数据的作业抢先使某些字段无效。当您填充对象时,您知道发生了这种情况,因为存在对不存在的数据的引用,并且您知道需要刷新它。 (是在缓存层还是在应用程序层处理刷新,这是一个设计决策,可以采用任何一种方法。)

相关问题