Open10

sidekiqとは

いいづかいいづか

Sidekiqって何?

Simple, efficient background processing for Ruby.

Rubyのためのシンプルで効率的な非同期処理を行うためのgem

Sidekiq uses threads to handle many jobs at the same time in the same process. It does not require Rails but will integrate tightly with Rails to make background processing dead simple.

Sidekiqは多くのジョブを同時に処理することができる。
Railsがなくても使えるけど、Railsと一緒に使うと非同期処理の実装がをめっちゃシンプルになって良い。

https://github.com/sidekiq/sidekiq#readme

いいづかいいづか

非同期処理って何?

処理自体は今この場でやらない = 非同期的

「リクエスト受付完了したよ、裏でよしなに終わらせるから、次のリクエストちょうだい」という処理。

【処理順番】
リクエストが来る → 受付結果のみのレスポンスを返す → 処理する

リクエストを受け取ってから、受付完了のレスポンスのみを返し、その後に処理を行う形式の処理。

じゃあ同期処理って何?

処理自体を今この場でやる = 同期的

「リクエスト受け付けたよ、今からやるね!次のリクエストは終わるまで待ってて」という処理。

【処理順番】
リクエストが来る → 処理をする → 処理結果のレスポンスを返す

リクエストを受け取ったら、その場で処理が実施されて完了するまで待たされる形式の処理。

https://aws.amazon.com/jp/builders-flash/202206/master-asynchronous-execution-01/?awsf.filter-name=*all

より正確に

通常のプログラミングにおける実行時の処理は、ソースコードの命令語を先頭から順番に一つずつ実行します。上から順に実行していくので、1つの処理が終わるまで待ち、次の処理を行います。いわゆる順次処理です。
一方で、非同期処理では異なる処理を行います。同期処理同様、コルーチンを先頭から順番に処理していきますが、1つの非同期処理が完了するのを待たずに次の処理を行います。例えば二つの処理がある状態では、一つの処理を一定量進めた後にストップし、もう一つの処理を同様に進めた後ストップし、最初にストップした処理を再開するということができます。したがって、これを繰り返すことで並列して複数の処理を実行することが可能となります。このように、非同期処理では同時に複数の処理を実行することになります。

https://gimo.jp/glossary/details/async.html

いいづかいいづか

ちょっと脱線

非同期処理を実現するための技術

主に以下2つの「通信形態」が使われる。

  • キュー
  • トピック (Public / Subscribe モデル)

どちらも、リクエストの受付から処理までを担ってくれるが、
受付完了レスポンスを戻した後の、処理実行の進め方が異なる。

キューってどんなことするの?

リクエストを受け付けたら、メッセージ(≒処理内容)がキューに格納される
処理実行側が、キューに入っているメッセージを随時確認しに行って、メッセージがあれば処理を実行する

処理実行されるプロセス:通常は、メッセージをとりに行っているプロセス1つだけ
処理実行タイミング:処理実行側がメッセージを確認しに行ったタイミング(こっちで指定する感じになる)

https://aws.amazon.com/jp/message-queue/

トピック (Public / Subscribe モデル) ってどんなことするの?

リクエストを受け付けたら、メッセージがトピックに格納される
トピックに格納されたら、トピックを購読している処理たちにそのままメッセージが送られる

処理実行されるプロセス:トピックを購読している1つ〜複数のプロセス
処理実行タイミング:トピックにメッセージが格納されたらすぐ(こちらで指定しなくても良い)

https://aws.amazon.com/jp/pub-sub-messaging/

簡単に2つはどう違う?

キュー:処理実行側がキューにメッセージ(≒処理内容)をとりに行く(処理プロセスは能動的)
トピック:トピックが処理実行側に(≒処理内容)を送る(処理プロセスは受動的)

いいづかいいづか

ちょっと脱線

キューとトピックの使い分け例

例 1 : 任意のタイミング (バッチ処理等) でメッセージを一括処理したいケース

送信側が任意のタイミングでバラバラにメッセージを送信すると、受信側は、それに対応する処理、つまり常駐プロセスを起動し可用性を確保する必要があります。しかし、キューがキューイングをしてくれれば、バッチ処理をするときにキューから一括でメッセージを取得すればよく常駐して待機する必要がありません。このように受信側が任意のタイミングで受け取りたい場合、また、まとめて処理したいような場合にはキューが適しています。

例 2 : 受信側システムの稼働時間が、送信側と異なるケース

トピックを利用する場合、即時に受信者にメッセージが送信されます。その際に、受信者がメンテナンス等でダウンしていたらメッセージは処理されません。その場合、キューでキューイングし、受信者が処理できるタイミングで処理する方法が適しています。(ちなみに、第 3 回でご紹介する Amazon Simple Notification Service(SNS) には、送信先がダウンしている場合、リトライする機能があります)

例 3 : 複数の処理をシーケンシャルに処理をする必要がないケース

例えば、EC サイトで受注確定後に「配送処理」「メール通知処理」「請求処理」「ポイント計算処理」などの後処理がある場合、これらはシーケンシャルに順次実施する必要があるでしょうか ? 業務上、あるいは、システムの実行上の依存関係がなければ、「受注」イベントをもとに、並列で処理することが可能です。このような場合、下図のように「注文完了トピック」を作成し、「配送処理」「メール通知処理」などのバックエンドのプロセスが注文完了トピックを Subscribe していれば同じ受注情報が全Subscriver (購読者) に自動的に届き処理が並列で処理が可能となります。並列化することで処理完了までの時間の短縮も可能になりますし、いずれかのプロセスで問題が生じても、他のプロセスは影響を受けることなく処理ができ、影響を限定化することも可能です。

参照元:非同期処理を使いこなそう ! -第 2 回 非同期処理と同期処理の処理構造

例 4 : 受信者が増減する場合

例えば、例 3 のケースでは、注文処理サービスは、「在庫管理サービス」と「注文完了トピック」にデータを送り処理を完了させており、「メール通知サービス」「請求処理サービス」「ポイント計算処理サービス」とは疎結合です。疎結合化により、例えば、メール通知サービスが廃止されても、新たなサービスがトピックの Subscriber となりメッセージを受領するようになっても、注文処理サービスは影響を受けずに済み、追加・廃止対象のサービスで変更を完結できます。このように、トピックを入れることにより、バックエンドの機能追加・変更・廃止がより柔軟にできるようになります。

例 5 : キューイングをしつつ、同時に並列処理もしたいケース

上記の例では、トピックとキューを個別に適用したシーンを説明しましたが、トピックとキューを組み合わせて使うことでそれぞれの良い点を活かした構成も可能です。具体的には、「任意のタイミングで受領したい」バックエンドのプロセスにとっては、「キュー」を採用したいが、一方で、送信側としては、受信者の数に依存しない実装にしたい場合には、「トピック」にメッセージを送りたいと考えます。そのような場合には、下図のようにトピックの Subscriber をキューにすることで、送信者はトピックにメッセージを送り、受信者はキューからメッセージを受信するという方法を実現することが可能です。これは、Fan-out (扇を広げる形) と呼ばれるパターンです。

参照元:非同期処理を使いこなそう ! -第 2 回 非同期処理と同期処理の処理構造

https://aws.amazon.com/jp/builders-flash/202207/master-asynchronous-execution-02/?awsf.filter-name=*all

いいづかいいづか

Sidekiqでどうやって非同期処理を実装するの?

基本ここに全てが書いてある
すごいわかりやすい

https://github.com/sidekiq/sidekiq/wiki

大まかな実装の流れ

  • Railsから、Sidekiq::Clientのperform_asyncを呼び出す
  • ジョブがRedisにキューされる
  • Sidekiq::Serverがキューに置いてあるジョブを見に行って、適宜処理する

Sidekiqがjobを処理する流れ

参照:https://dev.icare.jpn.com/dev_cat/sidekiq/

いいづかいいづか

Redisとは?

Redis は、リモートディクショナリサーバー の略で、高速でオープンソースのメモリ内 key-value データストアです。

https://aws.amazon.com/jp/redis/

key-value データストアとは?

key-value データベースは、非リレーショナルデータベースの一種で、キーと値によるシンプルな方法を使用してデータを格納します。key-value データベースは、データを、キーと値のペアのコレクションとして格納します。

https://aws.amazon.com/jp/nosql/key-value/

Redisの特徴

メリット

  • 複雑な型のデータを操作し保存できる
  • 各種アプリケーションから高速でアクセスできる
  • 不整合が生じない
  • 各言語のクライアントで取得したデータを使用可能
    デメリット
  • データの揮発性がある
  • メモリの消費が大きい

https://www.fenet.jp/infla/column/technology/redisとはどのようなデータベース?3つの特徴や使い/#:~:text=Redisとは、メモリ上で動作するデータベースの,高速でアクセスできます。

SidekiqはデータストアにRedisを採用している

Sidekiq uses Redis to store all of its job and operational data.

https://github.com/sidekiq/sidekiq/wiki/Using-Redis