🐉

redis-client gem の使い方

2023/04/01に公開

redis gem があるのになぜ作られた?

redis-client gem が新しく作られた理由や経緯についてはこちらの記事が非常に詳しい

https://made.livesense.co.jp/entry/2022/08/01/083000

書き方の違い

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)

参照

https://github.com/redis-rb/redis-client

Discussion