自分のための覚書
TL;DR
- sidekiq proでは、server processが死んでも jobの復活がサポートされる
- sidekiq proにおいて、redis が死んでも、1000件程度のジョブならclientが保持し続けて、redisが復活したタイミングでenqueue してくれる
- ↑の状況において、client processが死ねば、蓄積された1000件のジョブは全て消える
- sidekiq enterpriseでは、unique な jobになるように諸々やってくれるが、完全に保証してくれるものでは無いので、そこんところを考えたjob設計にすること。
Pricing
- Pro
- $9,500 / yr
- Enterprise
- 250 thread $19,500 / yr
- 500 thread $23,400 / yr
Jobが失われないようにする仕組みについて
sidekiqにおいてjobが失われるケースは下記の3点
- redisに接続できないケース
- client processが死んだケース
- server processが死んだケース
この中でSidekiq Proが対策をしているのは redisに接続できない
と server processが死んだ
の2つのケース。
redisに接続できない場合
基本的に、下記の資料に書いてある内容。 https://github.com/mperham/sidekiq/wiki/Pro-Reliability-Client
通常版だと、redisが死んでいたらjobがpush出来ない。しかしPro版だとpushできなかったjobをclientのプロセスが保持しており、特定のjobがpushできるようになったタイミングで残っているjobも一緒にpushしてしまう。なお、client が保持できるjobの数は最新の1000件のみ。1000件を越えた場合は、永遠に失われてしまうので、そこは気をつけること。
server processが死んだ場合
- sidekiq basicは、Redis queueからのjobのフェッチにBRPOPを使っている
- sidekiqがjobを実行している最中にクラッシュしたら、そのjobは永遠に失われてしまう
- jobが失われない様に保証するための唯一の方法は、jobが完了するまでredisから削除しないこと
- sidekiq proはRedisのPROPLPUSH コマンドを利用してそれを実現している
- BROPLPUSH を使う場合は下記のように記述する必要がある
Sidekiq::Client.reliable_push! unless Rails.env.test? Sidekiq.configure_server do |config| config.super_fetch! config.reliable_scheduler! end
なお、super_fetchをする際は、redisデータベースの全走査を行うので、cache dataとjob dataで保持するredisを分けるのが望ましい。
JobのUnique制約について
大前提として jobは (class, 引数, queue)を組み合わせてuniqueであることが求められる。同じ引数のjobを異なるqueueに入れることができる。そのため、同一引数のjobで違う結果を期待してはいけない。基本的に unique な制約は時間に掛けることになる。
class MyWorker include Sidekiq::Worker sidekiq_options unique_for: 10.minutes def perform(...) end end
上記のような設定をした場合、jobが成功するか、jobが失敗して10分が経過するまで同一引数のjobを実行することは出来ない。