我正在使用 Redis 来存储每个哈希约 10 万条记录的哈希。我想在给定的哈希中实现过滤(分面)记录。请注意,一个哈希条目可以属于 n 个过滤器。
- 为每个过滤器实现一个排序的 SET。 SET 中的值对应于 HASH 中的键。
- 从给定的过滤器 SET 中检索 HASH 键。
- 一旦我从 SET 中获得 HASH 键,就从 HASH 中获取相应的条目。这应该给我所有属于过滤器的条目。
首先,上述方法在高层次上是否正确?
假设该方法没问题,但我缺少的一点是检索 HASH 条目的最有效实现是什么?我的想法是否正确,一旦我有了 HASH 键,我就应该使用 PIPELINE 对通过每个 HASH 键的多个 HGETALL 命令进行排队?有没有更好的方法?
我对使用 PIPELINE 的担心是我相信它会在为命令提供服务时阻止所有其他客户端。我将对过滤后的结果进行分页,每页 500 个结果。由于多个基于浏览器的客户端执行过滤,更不用说填充 SET 和 HASH 的后端进程,如果 PIPELINE 确实阻塞,听起来可能会有很多争用。谁能对此发表看法?
如果有帮助,我正在使用 2.2.4 redis,predis 用于 Web 客户端,servicestack 用于后端。
谢谢, 保罗
最佳答案
Redis 是一种无锁非阻塞异步服务器,因此在使用流水线时不会增加争用。 Redis 在收到每个操作后会愉快地处理每个操作,因此在实践中可以处理多个流水线操作。本质上,redis-server 并不关心操作是否是流水线的,它只是在接收到每个操作时对其进行处理。
流水线的好处是减少客户端延迟,而不是在发送下一个操作之前等待 redis-server 对每个操作的响应,客户端可以在一次写入中一次抽取所有操作,然后读回所有操作一次阅读中的响应。
我的 Redis mini StackOverflow clone 就是一个例子。每次点击都会调用 ToQuestionResults()
,因为操作是流水线式的,所以会在 1 个 Socket 写入调用上发送所有操作,并在 1 个 Socket 阻塞读取中读取结果,这比每次调用阻塞读取更有效:
My concern about using a PIPELINE is that I believe it will block all other clients while servicing the command.
这不是一个有效的问题,我不会过多考虑 Redis 在这里是如何工作的,假设它在流水线化不阻止处理其他客户端命令的情况下最有效地执行此操作。从概念上讲,您可以认为 redis-server 以 FIFO 顺序处理每个命令(流水线或非流水线)(即不会浪费时间等待/读取整个流水线)。
您描述的内容更接近 MULTI/EXEC(即 Redis 事务),其中所有操作在 Redis 服务器读取 EXEC(即 EOF 事务)时立即完成。这也不是问题,redis-server 仍然不会浪费任何时间等待接收您的整个事务,它只是将部分命令集排队到一个临时队列中,直到它接收到最终的 EXEC,然后立即处理所有这些。
这就是 Redis 如何通过处理每个命令来实现原子性,一次一个,一旦收到它们。由于没有其他线程,所以没有线程上下文切换,没有锁,也没有多线程问题。它基本上通过非常快速地处理每个命令来实现并发。
所以在这种情况下,我会使用流水线,因为它总是一个胜利,更多的是你流水线的命令越多(因为你减少了阻塞读取计数)。
关于hash - 过滤 Redis 哈希条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5675164/