通常 redis 是一個指令一個回應,
若一次要下多個指令,
就需要靠MULTI或pipeline來整批整行。
如果redis一次有好幾個指令要指行,
在 client 端可利用 MULTI 的指令來進行:
$ redis-cli
redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> set i5:user:1 twtw
QUEUED
redis 127.0.0.1:6379> set i5:user:2 wtwt
QUEUED
redis 127.0.0.1:6379> EXEC
1) OK
2) OK[code]
在MULTI之後所下的指令,
都被QUEUE住未執行,
一直到下了 EXEC 的指令,
才把所有QUEUE住的指令一次再執行,
回應的結果都在最後獲得回應。
而在ruby裡要執行multi的功能
[code]$ irb --simple-prompt
>> require 'redis'
>> redis = Redis.new
>> redis.multi do
?> redis.set 'i5:user:3','wtwt'
>> redis.get 'i5:user:3'
>> end
=> ["OK", "wtwt"]
另外也可以用把 multi 替換成 pipelined,
其他語法都一樣,
差別是什麼?
這篇裡面 https://github.com/redis/redis-rb 有提到
兩者的差異,
基本上是 pipelined 比 multi 快,
pipelined 是整批指令送出回應,
multi 看似整批,但還是一個個送,
但最後回應是從multi整個回來。
在這篇文章Request/Response protocols and RTT
主要是測試 有用 pipelined 跟沒有使用的回應的效能差別,
利用該文的程式碼,
我再加上一段有關 with multi 的測試來比較:
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
def with_multi
r = Redis.new
r.multi {
10000.times {
r.ping
}
}
end
bench("without pipelining") {
without_pipelining
}
bench("with pipelining") {
with_pipelining
}
bench("with multi") {
with_multi
}
執行的結果會發現:
$ ruby bench.rb
without pipelining 0.572608852 seconds
with pipelining 0.205889869 seconds
with multi 0.20942385 seconds
$ ruby bench.rb
without pipelining 0.571904261 seconds
with pipelining 0.187799676 seconds
with multi 0.193023878 seconds
速度上 pipelined > multi > without pipelined。
如果在程式語言裡,處理獲得一堆的陣列或hash,
需把資料塞入 redis 裡的 Sets 或 Lists,
用 pipelined 能較快地處理完成:
redis.pipelined{arr.each{|x| redis.lpush 'pg:1',x}}