redis 多重指令 MULTI 及 ruby 裡的 pipeline 的使用

通常 redis 是一個指令一個回應,

若一次要下多個指令,

就需要靠MULTI或pipeline來整批整行。

如果redis一次有好幾個指令要指行,

在 client 端可利用 MULTI 的指令來進行:

$ redis-cliredis 127.0.0.1:6379> MULTIOKredis 127.0.0.1:6379> set i5:user:1 twtwQUEUEDredis 127.0.0.1:6379> set i5:user:2 wtwtQUEUEDredis 127.0.0.1:6379> EXEC1) OK2) 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"enddef without_pipelining r = Redis.new 10000.times { r.ping }enddef with_pipelining r = Redis.new r.pipelined { 10000.times { r.ping } }enddef with_multi r = Redis.new r.multi { 10000.times { r.ping } }endbench("without pipelining") { without_pipelining}bench("with pipelining") { with_pipelining}bench("with multi") { with_multi}

執行的結果會發現:

$ ruby bench.rbwithout pipelining 0.572608852 secondswith pipelining 0.205889869 secondswith multi 0.20942385 seconds$ ruby bench.rbwithout pipelining 0.571904261 secondswith pipelining 0.187799676 secondswith multi 0.193023878 seconds

速度上 pipelined > multi > without pipelined。

如果在程式語言裡,處理獲得一堆的陣列或hash,

需把資料塞入 redis 裡的 Sets 或 Lists,

用 pipelined 能較快地處理完成:

redis.pipelined{arr.each{|x| redis.lpush 'pg:1',x}}


分享到:


相關文章: