今回は以下のKaigi on Rails 2024で発表された内容を見て学んだことをまとめていきます。
Sidekiq vs Solid Queue / Shinichi Maeshima - Kaigi on Rails 2024
バックグラウンドワーカーとは?
- リクエストの処理で時間がかかるタスクをアプリケーションサーバの代わりに実行する
- メール送信、外部Web APIの実行
- 再実行できるので外部のサーバが不調でも安心
- バッチ処理やCronジョブのようなタスクを実行可能
Railsにおけるバックグラウンドワーカー
Active Job
Active Job自体はラッパーとして機能し、実際の処理はSidekiq等のアダプタ経由で使用する
Active Jobは使わない方が良いという説もある
Sidekiqはデファクトスタンダードに
2024年時点でActive JobのアダプターとしてSidekiqが最も多く採用されている
Solid Queue
Rails8.0のデフォルトのアダプタ
Railsにおけるバックグラウンドワーカーにまつわる疑問
- Active Jobを使わない方が良いとはどういうこと?
- Solid QueueがRails8.0のデフォルトである、というなら今使用しているバックグラウンドワーカーから乗り換えた方が良い?
Rails向けバックグラウンドワーカーの歴史
- Active Job以前
-
BackgrouDRb
- Rails1~2で利用できた
- ジョブの情報は永続化しない
-
Delayed::Job
- Shopifyのコードからgemとして切り出された
- ジョブの情報をRDMかMongoDBをジョブのストレージとして使える
- ジョブ取得時にロックの競合でパフォーマンスが劣化する問題
-
Resque
- GitHub社が自社のバックグラウンドジョブを処理するために作成
- Redisをストレージとして選択したことで、Delayed::Jobのパフォーマンス問題を回避
-
Sidekiq
- スレッドベースで動き、Resqueと比べメモリ消費量が少ないことで利用者が増えた
Sidekiq Proの機能
- エンキュー時にRedisへのアクセスに失敗したら、メモリ上に失敗したジョブの情報をためておき、次のエンキュー時に再送する
- ジョブ実行中に何らかの要因でプロセスが死んても、ジョブの情報を失わずに再実行できる
-
- Active Job以後、Rails8.0以前
-
Active Job
- Rails4.2から登場
- バックグラウンドワーカー処理への共通インターフェースができた
- 他のRailsコンポーネントから非同期処理を扱うことができるように
Active Job経由ではなくSidekiqを直接使う説
- Active Job以前に作られたライブラリは独自のインターフェースと機能を持つ「Active Jobのアダプタ」として使われたときにライブラリの機能を完全に使えないケースがある
- 重複している機能もあり、仕様を理解していないとハマる可能性がある
-
Googjob
- Active Jobのアダプタとして動かす前提
- ストレージはPostgreSQL限定
- 大量のジョブを扱う時のロックの競合を、Advisory Locksを利用して回避している
-
- Rails8.0
-
SolidQueue
- Rails8.0からデフォルト
- ストレージはActive Record経由
SolidQueue誕生のきっかけ
- HEYにおけるResqueへの不満
- Solid Trifecta
- 2009年のディスク(HDD)性能と今のディスク(SSD)の性能を比べると約100倍良くなっており、DBに対するRedisの優位性は当時と比べて相対的に減っている
- rails newした時の構成要素を1つ減らせる(One Person Framework)
- SKIP LOCKED
- 大量のジョブを扱えるようになった
-
バックグラウンドワーカーの選定
ストレージ
- RedisかRDB
- 小さいサービスであればアプリケーションのDBと相乗りできるSolid Queueが管理しやすい
- Redis運用コストが削減できる
- 大量のジョブを扱うサービスであればSidekiq(Redis)に優位性がある
- Sidekiqだと2万ジョブ/秒の実績あり
インターフェース
- Solid QueueはActive Job前提なので迷わないメリットがある
機能
- Solid Queueは現時点では基本的なバックグラウンドワーカーに必要な機能を持っている
- Sidekiqは上記以上の機能を持っている
- Batch
- 複数のジョブをバッチという単位でまとめて管理し、バッチのジョブ全体が終了したことをきっかけに発火するコールバックを設定できる
- Rate Limiting
- 特定の処理の実行数に制限
- 外部のAPIをワーカから叩くケースで、APIが同時アクセス制限をかけている場合に使える
- Encryption
- Redisに渡すデータの一部を自動的に暗号化、複合する
- Batch