【问题标题】:Redis cache designRedis缓存设计
【发布时间】:2015-03-10 18:55:36
【问题描述】:

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

我有称为“容器”的对象

我想通过id 查找这些容器。通常一次有多个容器。查找并不一致,每个用户都有一组不同的查找 ID。

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

但我必须一次有效地查找多个容器。我注意到了哈希数据类型,所以现在我这样做了”hmset containers [id] [serialized json]。这样我可以通过hmget containers 1 3 4 来返回容器 1、3、4。

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

谢谢

【问题讨论】:

    标签: caching redis


    【解决方案1】:

    这里有几个问题。我会尽我所能回答所有的。

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

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

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

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

    正如您所提到的,HMGET 可以让您一次检索多个容器。此选项比选项 #1 的内存效率略高。这也允许您的顶级密钥空间保持较小,因为它不会随每个容器一起增长。这个优势并不显着,但只是一个小的管理帮助,因为您可以使用KEYS 命令来减轻痛苦。它应该和选项 #1 一样快。

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

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

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

    使用这种方法在一个命令中检索多个容器会更加困难,因为它需要pipeliningLua scripting

    结论

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

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

    我可以在场景中使用expire 键吗?

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

    【讨论】:

    • 这非常有帮助。感谢您花时间为我分解它。你能展示如何使哈希字段过期吗?根据我的研究,看起来expire 仅适用于常规密钥。或者您是否只允许使整个散列过期,而不是特定散列的字段? redis.io/commands/expire
    • expire 适用于键,无论值的类型如何。您只能使键过期,而不是散列中的字段,因此在散列上使用它会使整个散列过期。这是上面选项 #2 的缺点。
    猜你喜欢
    • 2018-05-25
    • 2022-11-25
    • 1970-01-01
    • 2015-11-27
    • 2017-12-22
    • 2014-07-14
    • 2018-04-25
    • 2018-01-30
    相关资源
    最近更新 更多