Redis键命名约定?


226

Redis中密钥的正常命名约定是什么?我已经看到值之间有分隔符,:但是我不确定正常的约定是什么,为什么?

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

user:00

如果用户的ID是 00

您是否可以仅查询密钥的开头以返回所有用户?

我主要是希望通过研究对人们有用的方式以及他们为什么选择它们的方式来避免将来出现任何问题。

Answers:


205

Redis中密钥的正常命名约定是什么?我已经看到了以:分隔的值,但是我不确定正常的约定是什么,或者为什么。

是的,:在命名键时,冒号是一种约定。在Redis网站上的教程中指出:尝试坚持使用模式。例如,“ object-type:id:field”可能是一个不错的主意,例如在“ user:1000:password”中。我喜欢在多词字段中使用点,例如在“ comment:1234:reply.to”中。

您是否可以仅查询密钥的开头以返回所有用户?

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

解决此问题的更合适的解决方案是创建专用密钥,让我们命名为users,它将存储所有用户密钥,例如,以列表设置数据结构的形式。


1
scan不是@EranH选项,这是迭代密钥的最佳实践。scan用于逐步迭代元素集合。
基什·帕瓦尔

2
@ yojimbo87因此,有两个命令可以说,第一个是创建密钥,例如-user:808021:password = XYZ,第二个是将密钥放入注册表或索引(set),但是当一个命令成功执行时会发生什么,并且其他失败表示密钥已创建,但未在注册表中输入。
LoveToCode

1
@LoveToCode您可以使用事务处理,该事务应保证将执行所有操作或不执行任何操作。
yojimbo87 '16

2
我还注意到Redis Desktop Manager(Redis客户端工具)还将冒号':'视为分隔符,并显示了多个分组在一起的密钥
Adam Rotaru

1
我认为唯一的价值是永恒的。轻松执行以下操作:$redis->delete($redis->keys('user:password:*'));
蜡笔小新

26

我们使用冒号(:)作为名称空间分隔符,并使用散列(#)表示键的id部分,例如:

logistics:building#23

如果您有更多的键(如语言环境,类别等),则最佳名称约定是什么?{resource}:{key}#{value},{key}#{value} =>文本:locale#en,category#15吗?还是您有其他建议?
fsasvari

1
在我的示例中,“ building”只是“ collection”的名称,而23是自定义“ id”。如果您有一个locale = en且category = 15的复合ID,则实际ID可能为{en,15},所以namespace:texts#{en,15},或更冗长的是:namespace:texts#{locale = en,category = 15}。但这只是一个想法,我从来没有像这样使用过。注意不要更改id元素的顺序,因为当然不会找到密钥。实际上,与其在您的键名中编码这种复杂性,不如考虑使用redis数据结构。看看redis.io/topics/indexes
The Nail

16

约定似乎是冒号(:),我是一名Web开发人员,因此我个人更喜欢将斜杠(/)用作分隔符。在URL中,斜杠已经是非常重要的分隔符,它们是统一资源定位符,因此是资源的键。为什么对冒号(:)采取不同的方法?有什么帮助吗?

考虑以下示例:

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

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

它存储在哪里?我们使用Redis和斜杠,因此显而易见:

toy/234

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

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

用户使用key请求对象toy/666。如何从Redis获得它?与Node.js相关的示例:

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

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

注意:始终确保用户只能访问您想要的内容。user/1/password评论员所指出的,上面的原始URL到密钥方法也能够获取。如果将Redis用作公共只读缓存,则应该不会有问题。


24
…方便,而且几乎令人反感的不安全感。您请求得到curl http://example.com/api/user/1/password'd或类似的东西。(就
说吧

3
冒号,哈希和斜线可用于指定不同级别的嵌套,例如User#23:uploads:my/path/to/file.ext
化身

31
请不要将用户输入作为输入数据库的键。
莱尔(Lyle)

1
我喜欢您认为自己喜欢斜杠的方式,因为您是一名Web开发人员。
赫克托·奥多涅斯'18

@ELLIOTTCABLE谢谢,添加了有关不安全因素的说明。如果将Redis用作公共只读缓存,您是否在此方法中看到任何问题?
阿克塞利·帕伦(AkseliPalén)

6

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

我已经尝试过使用ASCII NUL字符作为分隔符(因为Redis和Python都是8位纯净的)。如果您正在查看原始键,这看起来有点丑陋,但其想法是将其隐藏在抽象层后面。只要保证命名空间的组成部分不使用冒号和竖线符号,或者您愿意根据需要对每个组成部分进行编码,冒号和竖线符号都是很明显的选择。但是,如果要对它们进行编码,则需要开发抽象层,并且无论如何都要避免查看原始键……这使我回到在推理中仅使用\ 0的方式。

我将对此感兴趣,看看是否有其他意见。


0

为了您的用例,在我看来是HSET / HGET将是一个更好的选择。还有HKEYS命令。

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

然后,您可以具有以下结构:

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

要么:

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.