🐯

Sidekiq(サイドキック)とは何なのか、調べてみた | Offers Tech Blog

2023/01/30に公開

こんにちは!🐯
プロダクト開発人材の副業転職プラットフォーム Offers を運営する株式会社 overflow のエンジニアの Taiga🐯 です。

Sidekiq のイメージ画像のように格闘技[1]を始めたのですが、やはりデスクワークの多いエンジニアに運動は必要なのでおすすめですw

さて、今回は Sidekiq について何となくで使っていたものの、しっかり実態を知りたいなと思い筆を執っている次第でございます。

この記事では、Sidekiq とは何なのか。よく使うメソッドや実態の紹介をします。Sidekiq 初見の人が「ふーん、概要は分かった😽」となるような内容を執筆していきます。

Sidekiq とは

Sidekiqのロゴイメージ

(英語)

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と緊密に統合し、バックグラウンド処理を非常にシンプルにする予定です。

公式ドキュメント からの引用で恐縮ではありますが、「スレッド[2]を使用してバックグラウンドで処理をしてくれるもの」といった認識でいいかと思います。

Sidekiq を使うタイミングとしては、リアルタイム性を伴わない/負荷の重い処理を先にバックグラウンドで実行させて次の処理に移りたい。といったケースで利用します。

概要についてはここまでにしておきます。より詳しい説明や使用方法に関しては、公式ドキュメント を一読しておくと良いと思います!

(どのように書くかは次章で説明致しますが、紹介YouTube もあるので、イメージしやすいかもです)

Sidekiq が行う処理の流れ

バックグラウンドジョブシステムは非同期に処理したい内容を管理するサーバ(Client)と、それらを処理するワーカー(Worker)から構成されています。

Sidekiq を使用して非同期的に Job を処理するためには、Rails サーバの他に Redis と Sidekiq を起動しておく必要があります。非同期処理したい内容(Job)を予めデータストアに格納します。

Sidekiq の処理としては下記 2 つがメインです。 公式参考

  1. Sidekiq Client が、Job を Redis に格納する処理を担う
  2. Sidekiq Server が、Redis から Job を取り出し Job の実行を担う

処理の一例

model 等に非同期処理を行いたいメソッドが定義してあるという設定 (※コードは仮のものです)で、実際に流れを記載していきます。

class User
  # バッチ処理とかで実行されるという仮設定  
  def self.some_method
    UserDoSomethingWorker.perform_async(self.id)
  end
end

後述する Worker を定義後、perform_async をします。

(perform_asyncメソッド の実態は client_pushメソッド となっており、redis への pushメソッド を呼び出し、Redis に push し、Job を enqueue しています(すべて処理を追うのは記載量が増えるので割愛しました)。)

class UserDoSomethingWorkerWorker
  include Sidekiq::Worker
  sidekiq_options queue: :event

  def perform(user_id)
    user = User.find(user_id)
    user.heavy_some_method
    # 非同期処理したかった処理を書く
  end
end

Redis に enqueue 後、queue から Job を取り出して performメソッド を dequeue(実行)します(詳細は割愛)。

上記の処理の説明は、公式ドキュメントのThe-Basics に記載があるので興味がある方はそちらを読んでみてください。

この一例の場合、heavy_some_method を同期的に処理すると、実行結果を待ってから次の処理を行うことになってしまいますが、非同期処理なのでバックグラウンドで処理してくれます。

Sidekiq でよく使うメソッドや tips

ここではメモがてら、よく使うメソッドや tips を記載します。

  • perform_async にわたす引数は id にする → シリアライズされるためパフォーマンスが低下する。なるべく id を渡して Worker 内でロードするようにした方が◎
  • sidekiq_options queue: :event, retry: num → デフォルトではリトライは、リトライ回数の 4 乗+15 秒間隔で行われる
  • メール処理などといった複数行われるとまずい処理は retry: false にしておく(副作用を考える)
  • Worker 名は、動作を表すべき
  • デバッグ時は、 UserDoSomethingWorkerWorker.new.perform 等にすると即時実行されるのでデバッグしやすい
  • perform_in → 指定時間待ってから実行される
  • perform_at → 第一引数に timestamp を指定すれば、その時間に実行される

(大抵ドキュメントのWiki に記載があるので(上記内容も)、一読しておくと吉です!)

おまけ

なぜサイドをキックするのだろうと疑問に思い Sidekiq 由来(origin)を日本語/英語で調べましたが、未だキックの由来は不明です...

Side(横で処理する) + kiq(キューをエンキュー&デキュー) で処理をキックしているから来ているのでしょうか...知っている方いたらこっそりコメント欄で教えて頂けますと幸いでございますw

Sidekiq のメソッドを調べていたら、 Sidekiq.❨╯°□°❩╯︵┻━┻ という謎コマンドが存在したので実行したところ、落ち着けと言われました。こういう遊び心、いいですね。

[13] pry(main)> Sidekiq.❨╯°□°❩╯︵┻━┻
Calm down, yo.
nil

ちなみにこちらの落ち着け君メソッド(呼び方謎w)、過去には test 書かれていたようですが、
現在の main ブランチからテストは抹消されていました...w

  describe "❨╯°□°❩╯︵┻━┻" do
    before { $stdout = StringIO.new }
    after  { $stdout = STDOUT }

    it "allows angry developers to express their emotional constitution and remedies it" do
      Sidekiq.❨╯°□°❩╯︵┻━┻
      assert_equal "Calm down, bro\n", $stdout.string
    end
  end

it の文章がジワりますね。

最後に

今回は、Sidekiq についての概要や流れ、よく使うメソッドの説明について執筆しました。
少しはイメージがつけば幸いです。
Sidekiq は便利なので、なるべく負荷の重い処理等は意識して非同期処理として扱っていきたいですね。

最後にはなりますが、本記事を最後まで読んで頂き、ありがとうございました。「こんな記事を書いてほしい!」などありましたらコメントいただけると幸いでございます。

関連記事

https://zenn.dev/offers/articles/20220602-binding-pry-debug-tips

脚注
  1. 始めたのはキックボクシングなんですが、Sidekiq アイコンの人がおこなっているのは何の競技なのでしょう?帯をしていることからキックボクシングではなく空手の可能性が高そうですが、この Gem って国産じゃないよなと思いつつ..w。知っている人いたら教えてくださいw ↩︎

  2. プログラムの処理の実行単位 ↩︎

Offers Tech Blog

Discussion