从Redis读取多个哈希的最快方法是什么?

时间:2015-05-26 14:05:02

标签: redis predis

我有LIST包含指向某些HASH数据的指针。类似的东西:

[LIST] app:1 ["article1", "article2", "article3" ...]
[HASH] article1 {title: "Hello", description: "World"}
[HASH] article2 {title: "Hello", description: "World"}
[HASH] article3 {title: "Hello", description: "World"}

收到此请求后:

api/v1/app/1/articles/20

我执行以下操作:

$pointers = $this->redis->lrange($appID, 0, $request->articles);
$articles = [];

foreach($pointers as $pointer) {
   $articles[] = $this->redis->hgetall($pointer);
}

所以我最终得到:1次lrange来电,然后是$request->articleshgetall次来电。我想问一下这可能是最快的解决方案吗?

我想到了:

  1. 做HMGET

  2. 执行MULTI / EXEC

  3. 使用LUA编写此功能并将其置于单个命令中。

  4. 有什么想法吗?

2 个答案:

答案 0 :(得分:2)

如果您只是存储文章数据,我发现您应该将每个文章属性存储在每篇文章的哈希中,但是您应该构建一个哈希,其中key应该是文章标识符,而值应该是JSON - 序列化的对象字符串。

通常在需要访问某些对象的特定属性时使用哈希值,但我猜您正在获取这些文章以将其列在某些UI中,因此没有理由在每篇文章中使用哈希值。无论如何,每篇文章的散列和作为JSON的所有文章的散列都可以共存:如果你需要访问特定文章属性而不获取整个对象,则每篇文章的散列,以及所有文章的散列以获得整个对象或列出对象。

想象一下,你可以避免使用这种方法调用Redis。您从列表中获取所有文章标识符,然后使用单个hmget命令在一次旅行中获取所有文章。由于您正在使用lrange我了解您并不会获得所有文章,但您正在使用分页

您的API将所有JSON对象作为字符串获取,并将它们直接返回给API客户端。

您对API资源URI的一些担忧

我检查了你的陈述:

  

收到此请求后:

     

API / V1 /应用/ 1 /物品/ 20

在REST中,articles/20让我"通过id"获取第20条而不是"得到20篇文章"。

让我建议你,我可以采用两种方法解决范围问题:

  • 使用查询字符串:api/v1/app/1/articles?startFrom=0&max=20(参数名称只是我的建议......)。
  • 使用HTTP标头。您可以发送HTTP标头以及MyApi-Range: 0 20之类的请求,其中0是起始位置,20是最大页面大小(即最大结果)。

更新:有关该方法的一些细节。

OP在一些评论中表示:

  

我们在任何时候都只保留20篇文章。所以,当一个应用推动一个   新文章,最后一篇从列表中删除,新的一篇文章被添加   列表左侧。然后我们删除artice:{ID}哈希。跟你的   解决方法,我需要读取json串行字符串,删除   文章:{ID}属性,添加新的属性,然后保存(并覆盖   以前的密钥)。在后端方面还有一些工作要做。没有其他的   除了将它们保持为一种方式之外,还能以更快的方式获得这些哈希值   json序列?我知道LUA可以帮助Redis在一个命令中做到这一点,但我还是   不确定Redis上的负载是否保持不变。

我的方法是:

  • 文章存储在哈希articles中,其中键是文章ID和值JSON序列化文章对象:
[1] => {title: "Hello", description: "World"}
[2] => {title: "Hello 2", description: "World 2"}
....
  • 此外,您应该在名为 - articles:ids的列表中保留插入订单添加文章ID:

    [1,2]

  • 如果要存储新文章,请序列化文章对象,然后使用articles添加到hset哈希,并将文章ID添加到{{1} }使用articles:ids列表。 使用lpush命令来确保操作是以原子方式完成的!

  • 如果您想按插入订单获取文章,则需要获取MULTI文章ID并使用articles:ids获取所有文章。

  • 如您在评论中所述的20篇文章中,您需要使用hmget命令在articles:id中获取最新的文章ID,并使用{ {1}}命令从rpop哈希中删除文章对象。 使用hdel命令来确保操作是以原子方式完成的!

更新2:一些澄清

OP说:

  

如何使用HMGET检索文章?那会怎么样?   哈希量表,当它包含大约一百万个密钥?

关于如何使用articles检索文章,这很简单:您获取列表项(可能使用MULTI)并将所有获取的ID作为{{1的参数从哈希中获取整篇文章。

关于如何使用数百万个密钥缩放哈希值,请检查hmget时间复杂度是否为lrange,这意味着密钥数量不会影响访问时间,而hmget(因为它' 哈希多次获取)是hget因为访问时间增加了获取的密钥数量(而不是存储的密钥总数)哈希)。

顺便说一句,由于Redis 3.x是黄金版,并且由于Redis Cluster而在可扩展性方面提供了很大的改进,您应该了解有关此新功能的更多信息以及sharding如何提供帮助大数据集。

答案 1 :(得分:0)

将您的哈希键从article1更改为app1:article1