过滤Redis哈希条目

时间:2011-04-15 10:03:29

标签: hash filter redis facet

我正在使用redis存储哈希,每个哈希有大约100k条记录。我想在给定的哈希中实现过滤(分面)记录。请注意,哈希条目可以属于n个过滤器。

阅读thisthis之后,我应该这样做:

  1. 为每个过滤器实施一个排序的SET。 SET中的值对应于HASH中的键。
  2. 从给定的过滤器SET中检索HASH密钥。
  3. 一旦我从SET获取HASH密钥,就从HASH中获取相应的条目。这应该给我所有属于过滤器的条目。
  4. 首先,上述方法是否在高水平上正确?

    假设方法没问题,我缺少的是检索HASH条目最有效的实现方法是什么?我是否正确地思考一旦我有HASH键,我应该使用PIPELINE来排队通过每个HASH键的多个HGETALL命令?有更好的方法吗?

    我对使用PIPELINE的担心是我相信它会在服务命令时阻止所有其他客户端。我将分页过滤结果,每页500个结果。有多个基于浏览器的客户端执行过滤,更不用说填充SET和HASH的后端进程,如果PIPELINE阻塞,则听起来有很多争用的可能性。任何人都可以提供这方面的观点吗?

    如果它有助于我使用2.2.4 redis,则为后端的Web客户端和服务栈提供预测。

    谢谢, 保罗

3 个答案:

答案 0 :(得分:5)

个别操作会阻止,但无关紧要,因为它们不应该长时间运行。听起来你正在检索比你真正需要的更多信息 - 当你只需要500时,HGETALL将返回100,000件物品。

发送500个HGET操作可能会起作用(假设集合存储了散列和密钥),尽管使用散列可能是过早优化的情况 - 使用常规密钥和MGET可能会更好。

答案 1 :(得分:4)

Redis是一个无锁无阻塞异步服务器,因此在使用管道传输时没有添加争用。 Redis在收到每个操作后立即愉快地处理它们,因此在实践中可以处理多个流水线操作。本质上,redis-server实际上并不关心操作是否是流水线操作,它只是在接收到它们时处理每个操作。

流水线技术的好处是减少客户端延迟,而不是在发送下一个操作之前等待redis-server对每个操作的响应,客户端可以在一次写入中立即泵送所有操作然后读回所有操作单次阅读中的回答。

这个实例的一个例子就是在Redis mini StackOverflow clone中,每次点击都会调用ToQuestionResults()因为操作是流水线的,所以在1个套接字写入调用上发送所有操作并在1个套接字阻塞中读取结果读取哪个更有效,而不是每次调用阻塞读取:

https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/IRepository.cs#L180

  

我对使用PIPELINE的担忧是   我认为它会阻止所有其他   客户服务命令时。

这不是一个有效的问题,我不会想到Redis如何在这里工作,假设它正在最有效地进行,其中Pipelining不会阻止其他客户端命令的处理。从概念上讲,您可以认为redis-server以FIFO顺序处理每个命令(流水线或非流水线)(即等待/读取整个流水线时没有浪费时间)。

您正在描述更接近MULTI / EXEC(即Redis Transactions)的内容,其中只要Redis服务器读取EXEC(即EOF事务),所有操作都会立即完成。这也不是问题,redis-server仍然不会浪费任何时间等待接收整个事务,它只是将部分命令集排队到临时队列中,直到它收到最后的EXEC,然后立即处理。

这就是redis在收到每个命令后,一次一个地处理每个命令,从而实现原子性的方法。由于没有其他线程,因此没有线程上下文切换,没有锁定,也没有多线程问题。它基本上通过快速处理每个命令来实现并发。

所以在这种情况下我会使用Pipelining,因为它总是一个胜利,所以你管道的命令越多(因为你减少了阻塞读取计数)。

答案 2 :(得分:2)

我认为你误解了流水线的作用。在发送所有命令时它不会阻塞。它所做的只是BUFFERING命令,然后在结束时立即执行所有命令,因此它们就像是一个命令一样执行。在任何时候都不会发生阻塞。 redis multi / exec也是如此。你在redis中最接近阻塞/锁定的是使用watch进行乐观锁定,如果在你调用exec之后写入了redis密钥,则会导致watch失败。

在管道块中调用hget 500次的效率更高,只需调用hmget('hash-key',*keys),其中keys是您正在查找的500个哈希键的数组。这将导致对redis的单次调用,这与流水线操作相同,但由于您没有循环使用ruby,因此应该更快地执行。