我创建了一个缓存(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
提出了另一个请求,我们将为该请求返回的字段更新本地时间戳。
如何以高性能的方式保存每个字段的时间戳?
考虑的选项:
每个值都有自己的时间戳。所有查找都将是O(1),但我们会有大量重复的时间戳数据。
"ref-user-1": {"type": "user",
"id": {"val": 1, "ts": "1557941674"},
"name": {"val": "bob" "ts": "1557941674"}}
将属性时间戳存储为属性集,每组单个时间戳。查找会很慢,但是会减少数据。更新也可能非常慢。如果我们可以将字段转换为哈希值,然后检查较大的哈希值是否包含较小哈希值中的所有字段,那就太好了。
"ref-user-1": {"type": "user", "id": 1, "name": "bob",
"field_sets": ["ts": "1557941674", "fields": ["id", "name"]] }
我没有考虑过的精美数据结构...
答案 0 :(得分:1)
就像一个古老的笑话所说:“计算机科学中只有两个难题:命名,缓存无效和一个错误。”
所以这是一个很难的问题,应该很困难。
我建议,重要的不是最近返回数据的时间,而是最近缓存数据的时间。否则,通常需要的数据可能会过时并无限期保持。 (看,我说过缓存失效很难!)
这表明时间戳记应基于缓存的最新更新时间。因此,如果数据不到1.5小时,则可以返回该数据。如果时间是1.5-2个小时,您可以掷硬币。 (随着翻转的可能性增加)。如果年龄较大,则将其视为无效。通过这种策略,即使非常活跃地访问数据,刷新数据也可能只请求一次。
此方法需要每个属性的时间戳。并且允许知道它已更改某些数据的作业抢先使某些字段无效。当您填充对象时,您知道发生了这种情况,因为存在对不存在的数据的引用,并且您知道需要刷新它。 (是在缓存层还是在应用程序层处理刷新,这是一个设计决策,可以采用任何一种方法。)