Help us understand the problem. What is going on with this article?

Sidekiqのベストプラクティス [翻訳]

Sidekiqのベストプラクティス

最終更新 2019/04/27 編集者 Madogiwa

Sidekiqのパフォーマンスを改善するには、次のルールに従ってください。

1. ジョブ引数を小さくシンプルにする

Sidekiqは、perform_async の引数をJSONとしてRedisに保存します。私はこのようなコードをたくさん見かけます。

quote = Quote.find(quote_id)
SomeWorker.perform_async(quote)

複雑なRubyオブジェクトはJSONに変換することができません。デフォルトでは to_s を使って変換することになり、その結果は #<Quote:0x0000000006e57288> のようになります。

たとえシリアライズができたとしても、キューに保存されている間に quoteオブジェクトの値が変更されたらどうなるでしょうか? 状態をSidekiqに保存するのではなく、シンプルなIDを保存するようにしてください。 そして、performメソッド内で実際に必要になったタイミングで、オブジェクトをfindするようにしてください。

SomeWorker.perform_async(quote_id)

perform_async メソッドに渡す引数は、 文字列、整数、浮動小数点、真偽値、null(nil)、配列、ハッシュ といったシンプルなJSONデータ型で 構成する必要があります 。これは、Rubyのシンボルを引数に 使用してはいけない ということを意味します。

SidekiqクライアントAPIはRedisへデータを送信するために JSON.dump を使用します。Sidekiqサーバーは、そのJSONデータをRedisからプルし、 JSON.load を使ってRubyオブジェクトに戻し、performメソッドに渡します。

シンボル、名前付きパラメーター、複雑なRubyオブジェクト(DateやTimeなど!)を perform_async メソッドに渡さないでください。 これらの値またはオブジェクトは、dump/loadの変換で正しく渡される保証がありません。

2. ジョブを冪等にし、トランザクションを利用する

冪等性とは、ジョブを複数回安全に実行できる性質のことです。例えば、エラーが起きた際のリトライの仕組みが用意されているとき、ジョブが半分だけ実行されて、そこで例外が起きて、正常に完了するまで何度も再実行されることがあります。

さらに具体的な例として、クレジットカードの取引を無効にし、請求金額の払い戻しがあることをユーザーにemailで知らせるジョブがあるとします。

def perform(card_charge_id)
  charge = CardCharge.find(card_charge_id)
  charge.void_transaction
  Emailer.charge_refunded(charge).deliver
end

emailの送信がバグで失敗した時に何が起きるでしょうか? void_transaction メソッドは、請求金額が既に返金済みのケースを正しく処理できるでしょうか? このような疑問を解消するためには、次の2つの方法が利用できます。

  • 1つめは、エラーが起きたときにデータベースへの変更を正しくロールバックするようトランザクションを使うという方法。
  • 2つめは、エラーが起きたときにそのエラーを適切に処理するような弾力性のあるコードを書くという方法です。

Sidekiqは、ジョブを 必ず1回 ではなく、 少なくとも1回 実行するという点を忘れないでください。

3. 並行性を取り入れる

Sidekiqは並列実行向けにデザインされています。そのため、ジョブを並列実行可能に設計すれば、Sidekiqのパフォーマンス上の恩恵を最大限受けることができるようになります。

Sidekiqは並行性を調整するための基本的な機能を持っています。例えば、1つのキューを処理するスレッドの数を事前に定義する機能などです。but your system architecture is much simpler if you don't have such specialization.

Sidekiqプロセスからのトラフィックが他のサーバーを圧迫しているのであれば、全体の接続数を制限するためにコネクションプールを利用することができます。

Sidekiqはジョブの中で並行性を調整するような機能は提供していません。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away