Redis缓存设计

5

我想在我的node.js API中集成缓存层。由于我以前没有构建过缓存层,所以有几个问题。

我有一个名为“容器”的对象。

我想通过id查找这些容器。通常一次会查找多个容器。这些查找不是一致的,每个用户都将具有不同的查找id集。

目前我不需要查询数据。因此,我开始使用键/值存储,其中键类似于"container_1",数据是序列化的json表示。

但是,我必须高效地查找多个容器。我注意到hash数据类型,因此现在我使用了hmset containers [id] [serialized json]。这样,我就可以使用hmget containers 1 3 4返回容器1、3、4。

将哈希存储在redis中作为实际对象是否更好,例如hmset containers:1 name test-container?这种处理数据的方式是否有效或正常?从时间复杂度的角度来看,这种策略如何扩展到数万或数十万条目?我能在集合上使用expire键吗?

谢谢

1个回答

7

这里有几个问题,我会尽力回答所有问题。

听起来你提出了三种可能的存储方案。以下是每种方案带来的后果的一些说明。

选项#1:将每个序列化容器存储在字符串键中

您可以使用MGET轻松检索多个容器。此选项在性能上应与将所有容器存储在单个哈希中相同。此选项将需要稍微更多的内存,因为顶级键比哈希字段具有更高的开销。您可以获得使用顶级键的优势,因此可以单独过期容器并在单个容器上使用其他键命令,例如DUMP/RESTORE/OBJECT/MIGRATE

选项#2:将所有序列化容器存储在单个哈希中,每个容器都在哈希的单独字段中

正如您所提到的,HMGET可以让您一次检索多个容器。这个选项比选项#1略微更节省内存。这也使得您的顶级键空间保持较小,因为它不会随着每个容器的增长而增长。这个优势并不显著,但是可以作为一个小型管理助手,因为您可以使用KEYS命令来减少疼痛。它应该和选项#1一样快。

选项#3:以某种未序列化格式将每个容器存储在哈希中,哈希字段对应于容器属性

如果每个容器都是JSON对象,则应该很好地映射。当对象的值不是简单字符串时,您仍然必须决定要做什么。您可能仍然需要将每个值存储为JSON或其他序列化格式。这个解决方案可能是最复杂的。当尝试在JavaScript中重新创建原始容器时,性能可能会受到影响,因为每个属性都需要被独立解析并重新组成最终对象,除非驱动程序在某个地方为您执行此操作。

这种方法可能使检索容器的特定字段变得更加容易和高效。

Retrieving multiple containers in one command would be more difficult with this approach as it would require pipelining or Lua scripting.

结论

每种方法的适用性、可扩展性和时间复杂度都极大地取决于您的访问模式。您是想通过容器属性值进行搜索吗?那么,选项#3开始变得有吸引力了。否则,选项#1和#2看起来最有吸引力。理想情况下,您将使用其他键为各种用例构建数据索引。您可能会拥有一个包含属于用户的容器ID的集合,或者一个按最后更新时间排序的容器ID列表。

所有这些方法都是合理的,并且使用额外的索引可以帮助确保任何一种方法都可以扩展。

我可以在集合上使用expire键吗?

可以。无论类型如何,您都可以使任何键过期。字符串、哈希、列表、集合等。


这非常有帮助,谢谢你花时间为我讲解。您能展示如何使哈希字段过期吗?根据我的研究,似乎 expire 只适用于普通键。或者您只允许过期整个哈希,而不是特定哈希的字段吗?http://redis.io/commands/expire - switz
1
“expire”适用于键,而不管值的类型。您只能使键过期,而不能使哈希中的字段过期,因此在哈希上使用它会导致整个哈希过期。这是上述选项#2的缺点。 - Carl Zulauf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接