ひとつの Rails アプリで Sidekiq worker によって使う Redis を分けたい。
Sidekiq のプロセスはひとつの Redis と接続することを前提としているので、複数の Redis と接続する場合には Redis の数に合わせて Sidekiq のプロセスが必要になる。
ここではふたつの Sidekiq プロセスを扱い、接続先の Redis の URL は全て環境変数に入れるものとして書く。
config/initializers/sidekiq.rb
Sidekiq.configure_server do |config| config.redis = { url: ENV['REDIS_URL'] } end Sidekiq.configure_client do |config| config.redis = { url: ENV['REDIS_1_URL'] } end
ざっくりと、 server は dequeue するほう (Sidekiq プロセス)、client は enqueue するほう (Rails アプリ) 。
client 側の設定は、とりあえずメインで接続するほうの Redis を設定しておけば良い。
Rails アプリの環境変数
REDIS_1_URL=redis://redis_1:6379
REDIS_2_URL=redis://redis_2:6379
Rails アプリ側では Redis の数だけ環境変数を用意する。
worker ひとつめ
ひとつめの worker はメインで接続するほうの Redis を使っているので普通に何も気にせず書いたら良い。
class Worker1 include Sidekiq::Worker def perform(*args) end end Worker1.perform_async()
Sidekiq プロセスの環境変数
REDIS_URL=redis://redis_1:6379
worker ふたつめ
ふたつめの worker は、呼び出し側で接続先が違うことを書かないといけない。 詳しくはここにかいてある。 Sharding · mperham/sidekiq Wiki
class Worker2 include Sidekiq::Worker def perform(*args) end end redis_2 = ConnectionPool.new { Redis.new(url: ENV['REDIS_2_URL']) } Sidekiq::Client.via(redis_2) { Worker2.perform_async() }
Sidekiq プロセスの環境変数
REDIS_URL=redis://redis_2:6379
さいごに
ここまで書いたあとに worker にオプションとして渡す方法を知った。Conection Pool を都度生成するのはやめたいし、呼び出し側じゃなくて worker 側に書いてあるほうがわかりやすいのでこっちのほうが良さそうと思った。
class Worker2 include Sidekiq::Worker sidekiq_options pool: ConnectionPool.new { Redis.new(url: ENV['REDIS_2_URL']) } end
とはいえ、Sharding 自体はおすすめはされていなさそう。
Part of the reason I don't document sharding well is because it is supposed to be painful/last resort. It's better to start breaking your monolith into smaller services if you've reached the point of saturating a Redis instance. Questions about Sharding usage · Issue #3605 · mperham/sidekiq