2013-10-09 68 views
8

试图为键值存储中的键定义一些策略(我们正在使用Redis)。密钥空间应该是:什么是管理键值存储中的键的好方法?

  • Shardable(可以引入更多的服务器,并展开它们之间的密钥空间)

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

  • 高效(尝试尽可能少地在数据库中使用键空间,以允许尽可能多的数据一个尽可能)

  • 作为碰撞越少越好(避免两个不同的对象键相等)


两种替代,我认为是这些:

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

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

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

非常感谢!

回答

8

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

这是如何与您设置的4个指南一起工作的?

可分片 - 这种方法是可分片的。每个键可以进入不同的分片或相同的分片,具体取决于您如何设置它。

命名空间命名空间作为避免碰撞的一种方法,可以使用这种方法。但是,名称空间作为组合键的方式并不成功。一般来说,使用键作为数据分组的方式是一个坏主意。例如,如果这个人从部门移到另一个部门呢?如果更改密钥,则必须更新所有引用 - 而且这会变得棘手。

最好确保密钥永远不会改变对象。然后可以通过创建单独的索引来对外进行分组。

例如,假设您想按部门,按工资范围,按地点对人员进行分组。这里是你会怎么做 -

  1. 个别人去单独的散与键persons:12321
  2. 每个组由创建set - 例如:persons_by:department - 并且只存储的数字标识符每个人在这个组。例如[12321,43432]。这样一来,你的Redis的整数集的优势

高效上面解释的方法是很有效的内存明智的。为了节省更多的内存,您可以在应用程序端进一步压缩这些键。例如,您可以存储p:12321而不是persons:12321。只有通过分析确定需要节省内存时,才应该这样做。一般来说,这是不值得的成本。

无碰撞这取决于您的应用程序。每个用户或个人应该有一个永不改变的主键。在你的Redis键中使用它,你不会碰撞。

你提到两个问题的办法,我会尽力解决这些问题

如果什么ID有一个冒号?

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

如果你确实必须在你的标识符中允许特殊字符,你必须在你的代码中编写一个小的包装来编码特殊字符。网址编码完全可以处理这个问题。

尺寸效率

有长密钥的成本,但它并不过分。一般来说,您应该担心值的数据大小而不是键。如果您认为密钥消耗太多内存,请使用类似redis-rdb-tools的工具来分析数据库。

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

+0

精彩的回答。非常感谢您花时间解决这个问题。我很抱歉没有为您点击“赏金”按钮,但这是我第一次使用它。谢谢! –

相关问题