我创建了一个缓存(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"]] }
我尚未考虑的花式数据结构...
正如旧的笑话所说:"计算机科学中只有两个严重问题。命名,缓存无效,并因一个错误而关闭。"
所以这是一个很难的问题,应该很难。
我建议重要的不是最近返回数据,而是最近如何缓存数据。否则,通常要求的数据可能会过时,并无限期地保持。(请参阅,我说的缓存无效很难!(
表明时间戳应基于最近更新缓存的时间。因此,如果数据少于1.5小时,则可以返回数据。如果年龄为1.5-2小时,则可以翻转硬币。(随着翻转的可能性的增加(。如果年龄较大,则将其视为无效。该策略使数据可能仅要求一次刷新一次,即使它非常积极地访问。
这种方法需要每个属性时间戳。并允许知道它更改一些数据以先发制于某些字段的作业。当您去填充对象时,您知道这发生了,因为有对数据的引用,并且您知道您需要刷新它。(无论是在缓存还是在应用层上处理刷新是可以采取任何一种方式的设计决定。(