【问题标题】:Redis key naming conventions? [closed]Redis键命名约定? [关闭]
【发布时间】:2011-10-21 09:10:08
【问题描述】:

redis 中键的正常命名约定是什么?我见过用: 分隔的值,但我不确定通常的约定是什么,或者为什么。

对于用户,你会做类似...

user:00

如果用户的 id 是 00

您是否能够只查询键的开头以返回所有用户?

我主要只是希望通过研究适合人们的方式以及他们选择这些方式的原因来避免将来出现任何问题。

【问题讨论】:

    标签: redis naming-conventions


    【解决方案1】:

    redis 中键的正常命名约定是什么?我见过 值由 : 分隔,但我不确定正常的约定是什么, 或者为什么。

    是的,冒号 : 是命名键时的约定。在 redis 网站上的 this 教程中声明:尝试坚持使用模式。例如“object-type:id:field”可以是 一个好主意,比如“user:1000:password”。我喜欢用点来表示 多词字段,如“comment:1234:reply.to”。

    你是否可以只查询键的开头来返回所有 用户?

    如果您的意思是直接查询以user: 开头的所有键,则有一个keys 命令。但是,此命令应仅用于调试目的,因为它是 O(N),因为它正在搜索存储在数据库中的所有键。

    更合适的解决方案是创建专用密钥,我们将其命名为users,它将存储所有用户密钥,例如listset数据结构中。

    【讨论】:

    • scan 不是选项@EranH。,迭代键是最佳实践。 scan 用于增量迭代元素集合。
    • @yojimbo87 所以会有两个命令让我们说第一个是创建密钥,例如 - user:808021:password = XYZ 第二个是将密钥放入注册表或索引( set ),但是什么当一个命令成功执行而其他命令失败时会发生这种情况意味着密钥已创建但未在注册表中获取条目。
    • @LoveToCode 您可以使用事务,它应该保证所有或不执行任何操作。
    • 我还注意到 Redis Desktop Manager(一个 Redis 客户端工具)也将冒号 ':' 视为分隔符,并显示组合在一起的多个键
    • 我认为唯一的价值是最后的。使执行以下操作变得容易:$redis->delete($redis->keys('user:password:*'));
    【解决方案2】:

    我们使用冒号 (:) 作为命名空间分隔符,使用哈希 (#) 作为键的 id 部分,例如:

    logistics:building#23
    

    【讨论】:

    • 如果您有更多的键,如语言环境、类别等,最好的命名约定是什么? {resource}:{key}#{value},{key}#{value} => texts:locale#en,category#15 ?或者你有什么其他建议?
    • 在我的示例中,“building”只是“collection”的名称,23 是自定义的“id”。如果你有一个 locale=en 和 category=15 的复合 id,那么实际的 id 可能是 {en,15},所以 namespace:texts#{en,15} ,或者更详细:namespace:texts#{locale =zh,类别=15}。但这只是一个想法,我从来没有这样使用过。注意不要改变 id-elements 的顺序,因为当然不会找到 key。实际上,与其在键名中编码这种复杂性,不如考虑使用 redis 数据结构。看看redis.io/topics/indexes
    • 听起来很有趣。可以在某种程度上使事情更具可读性。根据您编码到密钥中的数据,您可能需要转义/预处理一个字符(“#”)。
    【解决方案3】:

    约定似乎是冒号 (:) 我是一名网络开发人员,所以我个人更喜欢斜杠 (/) 作为分隔符。斜杠在 URL 中已经是非常重要的分隔符,它意味着 Uniform Resource Locators 这样的资源键。为什么要对冒号 (:) 采取不同的方法?有什么帮助吗?

    考虑这个例子:

    我们有一个用于玩具对象的RESTful API。有一个:

    http://example.com/api/toy/234 
    

    我们将它存储在哪里?我们使用 Redis 和斜线,所以关键是显而易见的:

    toy/234
    

    这是玩具的唯一钥匙。该密钥现在也可以在客户端使用:

    {
        key: "toy/234",
        color: "red",
        url: function () {
            return API_BASE_URL + this.key;
        }
    }
    

    用户请求一个带有键 toy/666 的对象。如何从 Redis 获取它?一个 Node.js 相关的例子:

    redis.get(key, function reply_callback(error, toystring) {
        var toy = JSON.parse(toystring);
        ...
    }
    

    无需将斜杠转换为冒号,反之亦然。方便,你不觉得吗?

    警告:始终确保用户只能访问您想要访问的内容。 正如评论员所指出的,上述原始 URL-to-key 方法也能够获取 user/1/password。如果您将 Redis 用作公共只读缓存,这应该不是问题。

    【讨论】:

    • ...方便,但几乎令人作呕不安全。你乞求得到curl http://example.com/api/user/1/password'd,或类似的。 (只是说。)
    • 冒号、散列和斜杠可用于指定不同级别的嵌套,例如User#23:uploads:my/path/to/file.ext
    • 请不要将用户输入作为进入数据库的键。
    • 我喜欢你认为你喜欢斜线的方式,因为你是一名网络开发人员。
    • @DanielSantos 感谢您提供详细信息。我想过这个。是的,URL 是一个 URI 方案。 URI 是更通用的概念。这里是不是太笼统了?一些 URI 似乎不使用斜杠来表示层次结构,例如 tel:+1-816-555-1212URI RFC 建议使用斜线作为层次结构,但不强制执行。因此,我认为将 redis 键与 URL 进行比较比 URI 更容易。
    【解决方案4】:

    我不知道是否真的存在广泛的 Redis 密钥命名“最佳实践”。

    我尝试过使用 ASCII NUL 字符作为分隔符(因为 Redis 和 Python 都是 8 位干净的)。如果您正在查看原始密钥,它看起来有点难看,但我们的想法是将其隐藏在抽象层后面。冒号和管道符号是显而易见的替代品,只要保证名称空间的组件不使用它们,或者您愿意根据需要对每个组件进行编码。但是,如果您要对它们进行编码,那么您会想要开发抽象层并避免查看原始密钥......这让我回到了在推理中只使用 \0 的问题。

    我很想看看是否有任何其他意见对此表达了意见。

    【讨论】:

    • 您的方法可以与使用制表符分隔值而不是 CSV 进行比较。选项卡不太可能需要预处理/转义,但有时可能会更棘手。对于计算机来说这无关紧要,但如果我们需要手动查看/编辑特殊字符,我们人类可能更容易出错。只是我的 2 美分,在做出此类决定时需要考虑。
    【解决方案5】:

    对于您的用例,在我看来 HSET/HGET 会更合适。还有HKEYS命令。

    所有这些命令都与 GET/SET/KEYS 具有相同的复杂性,那么为什么不使用它们呢?

    那么你可以有这样的结构:

    • 用户 > 00 > 价值
    • 用户 > 01 > 价值

    或:

    • 用户:用户名 > 00 > 值
    • 用户:用户名 > 01 > 值

    只需提取用户 ID 并将其用作哈希键。我个人更喜欢这种方法,因为它感觉更好,而且您可以轻松查询现有用户 ID。

    【讨论】:

      猜你喜欢
      • 2010-10-29
      • 1970-01-01
      • 2015-07-28
      • 2016-12-25
      • 2010-10-15
      • 2014-07-25
      • 2013-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多