Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hash 在Redis中以O(1)的时间复杂度获取最后20个哈希项?_Hash_Redis - Fatal编程技术网

Hash 在Redis中以O(1)的时间复杂度获取最后20个哈希项?

Hash 在Redis中以O(1)的时间复杂度获取最后20个哈希项?,hash,redis,Hash,Redis,按照Redis的建议,我必须尽可能使用哈希: 小散列是在一个非常小的空间中编码的,所以您应该试试 每次可能的时候都使用哈希来表示数据。对于 实例,如果在web应用程序中有表示用户的对象, 而不是对姓名、姓氏、电子邮件、密码使用不同的键, 对所有必填字段使用单个哈希 我将拥有数百万个项目,我正在尝试将帖子存储为散列: hmset post:1 title "hello" hmset post:2 title "hi" hmset post:3 title "g'day" 现在,我知道我可以像

按照Redis的建议,我必须尽可能使用哈希:

小散列是在一个非常小的空间中编码的,所以您应该试试 每次可能的时候都使用哈希来表示数据。对于 实例,如果在web应用程序中有表示用户的对象, 而不是对姓名、姓氏、电子邮件、密码使用不同的键, 对所有必填字段使用单个哈希

我将拥有数百万个项目,我正在尝试将帖子存储为散列:

hmset post:1 title "hello"

hmset post:2 title "hi"

hmset post:3 title "g'day"
现在,我知道我可以像创建哈希一样轻松地检索它:

hgetall post:1
问题是我想检索多个,可能是一行20个

我尝试了以下命令,但无效(当然没有3点):

给出以下错误:

(error) ERR wrong number of arguments for 'hgetall' command
我可以在客户端执行以下操作:

hgetall post:1
然后

等等。。但这将是对网络资源的巨大浪费,也是一个潜在的性能瓶颈,因为系统平均应能同时处理至少5000个用户/秒


如果我做的失败了,那么实现这一目标的最佳方式是什么?是否有一种方法可以一次性发送此命令,而不是按顺序发送?是否有可以在哈希上进行的lrange类型操作?

您的方向是正确的-对20篇文章中的每一篇文章逐个进行HGETALLs。然而,为了节省网络往返时间,请考虑使用Redis的管道,它本质上允许您对请求进行分组/批处理。或者,您可以通过实现自己的HGETALL版本来实现类似的结果,该版本通过服务器端Lua脚本接受多个键名。

正如您所指出的,您可以使用管道化的请求一次发送多个命令

发件人:

可以实现请求/响应服务器,以便能够 即使客户端尚未读取旧请求,也要处理新请求 响应。通过这种方式,可以将多个命令发送到 服务器根本不等待回复,最后读取 一步回复

这被称为流水线,是一种广泛使用的技术 几十年。例如,许多POP3协议已经实现 支持此功能,大大加快了 从服务器下载新电子邮件

如果我没有记错的话,这与HMSET命令使用的技术相同,它“管道化”了多个HSET命令

Redis站点的一个片段显示了一个使用Ruby进行管道连接和不进行管道连接的示例:

require 'rubygems'
require 'redis'

def bench(descr)
    start = Time.now
    yield
    puts "#{descr} #{Time.now-start} seconds"
end

def without_pipelining
    r = Redis.new
    10000.times {
        r.ping
    }
end

def with_pipelining
    r = Redis.new
    r.pipelined {
        10000.times {
            r.ping
        }
    }
end

bench("without pipelining") {
    without_pipelining
}
bench("with pipelining") {
    with_pipelining
}
Go还有一个名为Redigo的客户端,能够执行命令管道:

// Initialize Redis (Redigo) client on port 6379 
//  and default address 127.0.0.1/localhost
client, err := redis.Dial("tcp", ":6379")
  if err != nil {
  panic(err)
}
defer client.Close()

// Initialize Pipeline
client.Send("MULTI")

// Send writes the command to the connection's output buffer
client.Send("HGETALL", "post:1") // Where "post:1" contains " title 'hello' content 'hi' "

client.Send("HGETALL", "post:2") // Where "post:1" contains " title 'g'day' content 'g'mornin' "

// Execute the Pipeline
pipe_prox, err := client.Do("EXEC")

if err != nil {
  panic(err)
}

log.Println(pipe_prox)
这很好,只要您能够轻松地显示非字符串结果。。我仍在试图找到一种将结果转换为字符串的方法,现在我得到了以下结果:

[[[116 105 116 108 101] [104 105]] [[116 105 116 108 101] [104 101 108 108 111]]]
执行以下操作也无济于事:

result, _ := redis.Strings(pipe_prox, err)

log.Println(pipe_prox)
因为这是我得到的:

[]

我将在解决此问题后尽快更新此答案。

Lua或管道应该会有所帮助。此外,这可能表明您需要一个真正的数据库。
result, _ := redis.Strings(pipe_prox, err)

log.Println(pipe_prox)
[]