🐉
redis-client gem の使い方
redis gem があるのになぜ作られた?
redis-client gem が新しく作られた理由や経緯についてはこちらの記事が非常に詳しい
書き方の違い
redis
gem = Gem.latest_spec_for("redis")
gem.version # => #<Gem::Version "5.0.6">
gem.summary # => "A Ruby client library for Redis"
require "redis"
redis = Redis.new
redis.ping # => "PONG"
redis.flushdb # => "OK"
redis.set("key1", 1) # => "OK"
redis.get("key1") # => "1"
redis.get("key1").to_i # => 1
redis-client
gem = Gem.latest_spec_for("redis-client")
gem.version # => #<Gem::Version "0.14.1">
gem.summary # => "Simple low-level client for Redis 6+"
require "redis-client"
redis = RedisClient.new
redis.call("PING") # => "PONG"
redis.call("FLUSHDB") # => "OK"
redis.call("SET", "key1", 1) # => "OK"
redis.call("GET", "key1") # => "1"
redis.call("GET", "key1", &:to_i) # => 1
まとめて実行すると速い
value = redis.with do |r|
r.call("SET", "key1", "999") # => "OK"
r.call("INCR", "key1") # => 1000
end
value # => 1000
- 一行ずつ実行するのと変わらないけど速度的に毎回接続しないぶんだけ速くなるらしい
- ブロックの最後の戻値を返す
Transaction
redis.call("FLUSHDB")
values = redis.multi do |t|
t.call("INCR", "key1") # => nil
t.call("DECR", "key2") # => nil
end
values # => [1, -1]
- DB の Transaction 相当になる
- 個々の命令の戻値を配列で返す
並列実行
Good
value = redis.pipelined do |r|
r.call("SET", "key1", 1)
r.call("SET", "key2", 2)
end
value # => ["OK", "OK"]
Bad
value = redis.pipelined do |r|
r.call("SET", "key1", "999")
r.call("INCR", "key1")
end
value # => ["OK", 1000]
- 個々の命令の順序に依存していない場合のみ並列で実行できる
- 後者はたまたま動いているだけ
Pub/Sub
threads = []
# alice がチャットルームに参加したらメッセージが飛んできた
threads << Thread.start do
pubsub = RedisClient.new.pubsub
pubsub.call("SUBSCRIBE", "chat_room1")
pubsub.next_event # => ["subscribe", "chat_room1", 1]
pubsub.next_event # => ["message", "chat_room1", "bob: こんにちは"]
end
# bob があいさつした
threads << Thread.start do
pubsub = RedisClient.new.pubsub
pubsub.call("PUBLISH", "chat_room1", "bob: こんにちは")
end
threads.each(&:join)
参照
Discussion