在键值存储中管理密钥的好方法是什么?

时间:2013-10-09 18:16:48

标签: database namespaces redis key key-value-store

尝试为键值存储中的键定义一些策略(我们使用的是Redis)。键空间应为:

  • Shardable (可以引入更多服务器并在它们之间展开键空间)

  • 命名空间(应该有一些机制可以逻辑地“组合”键,例如通过域或相关概念)

  • 高效(尽量使用数据库中尽可能少的空间来存储密钥,以便尽可能多地提供数据)

  • 尽可能少碰撞(避免两个不同对象的密钥相等)


我考虑过的两个选择是:

  1. 使用名称空间的前缀,用某些字符分隔(如human_resources:person:<some_id>)。这样做的好处是它具有很强的可扩展性和易于理解性。缺点可能是冲突,具体取决于分隔符(如果id中包含字符:会怎样?),并且可能是大小效率(太多嵌套命名空间可能会创建非常长的密钥)。

  2. 使用一些数据结构(如Ordered Set或Hash)来存储名称空间。这样做的主要缺点是“可破坏性”的丢失,因为存储命名空间的结构需要在一个数据库中。

  3. 问题:在分片设置中管理密钥空间的好方法是什么?我们应该使用这些替代品,还是其他一些我们没有考虑过的更好的模式?

    非常感谢!

1 个答案:

答案 0 :(得分:8)

Redis世界中普遍接受的惯例是选项1 - 即由冒号等字符分隔的名称空间。也就是说,命名空间几乎总是一层深。例如:person:12321而不是human_resources:person:12321

这如何与您设定的4条指南一起使用?

Shardable - 此方法是可分的。每个键可以进入不同的分片或相同的分片,具体取决于您的设置方式。

命名空间命名空间作为避免冲突的方法适用于此方法。但是,作为组密钥的方式的名称空间不起作用。通常,使用密钥作为分组数据的方式是一个坏主意。例如,如果一个人从一个部门移动到另一个部门怎么办?如果更改密钥,则必须更新所有引用 - 这会变得棘手。

最好确保密钥永远不会更改为对象。然后可以通过创建单独的索引在外部处理分组。

例如,假设您希望按部门,按工资范围和按位置对人员进行分组。这是你如何做到的 -

  1. 个别人员使用密钥persons:12321
  2. 分别使用哈希值
  3. 为每个组创建set - 例如:persons_by:department - 并且仅存储此集合中每个人的数字标识符。例如[12321,43432]。这样,您就可以获得Redis'Integer Set
  4. 的优势

    高效上面介绍的方法非常有效。为了节省更多内存,您可以在应用程序端进一步压缩密钥。例如,您可以存储p:12321而不是persons:12321。只有在通过分析确定需要节省内存时才应该这样做。一般来说,这不值得花费。

    无碰撞这取决于您的应用程序。每个用户或个人都应该拥有永不改变的主键。在Redis密钥中使用它,就不会发生冲突。

    你提到了这种方法的两个问题,我将尝试解决它们

    如果ID有冒号怎么办?

    这当然是可能的,但是您的应用程序的设计应该可以防止它。最好不要在标识符中使用特殊字符 - 因为它们将在多个系统中使用。例如,标识符很可能是URL的一部分,冒号即使对于URL也是保留字符。

    如果您确实必须在标识符中包含特殊字符,则必须在代码中编写一个包装特殊字符的小包装器。 URL编码完全能够处理这个问题。

    尺寸效率

    长按键有成本,但不是太多。通常,您应该担心值的数据大小而不是密钥。如果您认为密钥占用了太多内存,请使用redis-rdb-tools等工具对数据库进行配置。

    如果您确定密钥大小有问题且想要保存内存,则可以编写一个小包装器,使用别名重写密钥。