Hash 过滤Redis散列项

Hash 过滤Redis散列项,hash,filter,redis,facet,Hash,Filter,Redis,Facet,我使用redis存储哈希,每个哈希大约有100k条记录。我想实现对给定散列中的记录进行过滤(刻面)。注意:散列条目可以属于n个筛选器 阅读之后,我似乎应该: 每个过滤器实现一个排序集。集合中的值对应于散列中的键 从给定的筛选器集中检索哈希键 一旦我有了集合中的散列键,就从散列中获取相应的条目。这将为我提供属于筛选器的所有条目 首先,上述方法在高水平上是否正确 假设该方法是正确的,那么我缺少的是检索散列项的最有效的实现是什么?我的想法对吗?一旦我有了散列键,我就应该使用管道将通过每个散列键的多个H

我使用redis存储哈希,每个哈希大约有100k条记录。我想实现对给定散列中的记录进行过滤(刻面)。注意:散列条目可以属于n个筛选器

阅读之后,我似乎应该:

  • 每个过滤器实现一个排序集。集合中的值对应于散列中的键
  • 从给定的筛选器集中检索哈希键
  • 一旦我有了集合中的散列键,就从散列中获取相应的条目。这将为我提供属于筛选器的所有条目
  • 首先,上述方法在高水平上是否正确

    假设该方法是正确的,那么我缺少的是检索散列项的最有效的实现是什么?我的想法对吗?一旦我有了散列键,我就应该使用管道将通过每个散列键的多个HGETALL命令排队?有更好的方法吗

    我担心使用管道会在为命令提供服务时阻塞所有其他客户端。我将分页筛选结果,每页500个结果。由于多个基于浏览器的客户端执行过滤,更不用说填充集合和散列的后端进程,如果管道阻塞,听起来可能会有很多争用。有人能对此发表看法吗

    如果有帮助的话,我将使用2.2.4 redis,predis用于web客户端,servicestack用于后端

    谢谢,
    Paul

    单个操作确实会阻塞,但这并不重要,因为它们不应该长时间运行。听起来你检索的信息比你真正需要的要多——当你只需要500个时,HGETALL将返回100000个项目


    发送500个HGET操作可能会起作用(假设集合同时存储哈希和密钥),但使用哈希可能会导致过早优化-您最好使用常规密钥和MGET。

    Redis是一个无锁非阻塞异步服务器,因此在使用管道时不会增加争用。Redis一收到每个操作,就会愉快地处理它们,因此实际上可以处理多个流水线操作。本质上,redis服务器并不关心操作是否是管道化的,它只是在接收操作时处理每个操作

    流水线的好处是减少客户端延迟,即客户端不必在发送下一个操作之前等待redis服务器对每个操作的响应,只需在一次写入中一次泵送所有操作,然后在一次读取中读回所有响应

    我的每次单击都会调用
    ToQuestionResults()
    ,这是一个实际例子,因为操作是管道化的,所以会在1个套接字写入调用上发送所有操作,并在1个套接字阻塞读取中读取结果,这比每次调用阻塞读取更有效:

    我对使用管道的担忧是 我相信它会阻止其他一切 为命令提供服务时的客户端

    这不是一个合理的担忧,我不会过度考虑Redis在这里的工作原理,假设它在流水线不阻止处理其他客户机命令的情况下最有效地工作。从概念上讲,您可以认为redis服务器以FIFO顺序处理每个命令(管道化或非管道化)(即,在等待/读取整个管道时不会浪费时间)

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

    这就是redis通过在接收到每个命令后一次处理一个命令来实现原子性的方式。因为没有其他线程,所以不存在线程上下文切换、锁和多线程问题。它基本上通过非常快速地处理每个命令来实现并发性


    因此,在本例中,我将使用管道传输,因为它始终是一个胜利,因此,管道传输的命令越多(因为您减少了阻塞读取计数)

    我认为您误解了管道的作用。它不会在发送所有命令时阻塞。它所做的只是缓冲这些命令,然后在最后一次执行它们,所以它们就像一个命令一样执行。任何时候都不会发生阻塞。redis
    multi
    /
    exec
    也是如此。在redis中,最接近阻塞/锁定的方法是使用
    监视
    进行乐观锁定,如果调用
    监视
    后已写入redis键,则会导致
    exec
    失败


    在管道块内调用
    hget
    500次更有效的方法是只调用
    hmget('hash-key',*keys)
    ,其中
    keys
    是您正在查找的500个哈希键的数组。这将导致对redis的单次调用,这与管道化调用相同,但执行速度应该更快,因为您没有在ruby中循环。

    感谢您的回复Tom。你说得对,我误解了HGETALL的目的。虽然你的回答很有用,但我不会接受,因为我觉得这并不能让我更接近原来的问题。我听到了你关于过早优化的说法,但似乎排序集是实现过滤的公认方式,而散列是存储“对象”的最佳方式。我觉得我只是在遵循最佳实践,而不是做任何不寻常的事情。我正在尝试做类似的筛选,但我要筛选大量(100万条记录)。你有没有找到更好的方法在redis中进行过滤?