Movatterモバイル変換


[0]ホーム

URL:


ゆうの技術部屋

ヘルステックWebエンジニア 3年目 (TypeScript, Next.js, Rails, GraphQL, AWS, Docker)

Railsにおける非同期処理 - Sidekiqを理解する

Sidekiqとは

Sidekiqは、Ruby/Railsアプリケーションのための非同期ジョブ処理ライブラリ。アプリケーションのパフォーマンスとユーザー体験を向上させるために、重い処理をバックグラウンドで実行できる

またJobとは、非同期で実行したい処理の単位のことで、Rubyのクラスとして定義する

主な用途

  • 大量データのインポート処理
  • 一斉メール送信
  • データ集計・分析処理
  • CSVデータの処理

Sidekiqのアーキテクチャ

Sidekiqシステムは3つの主要コンポーネントから構成されている

1. Sidekiq Client

  • 役割: JobをRedisに追加(エンキュー)する
  • 動作場所: アプリケーションコード内(Railsサーバープロセス内)
  • 使用例:MyWorker.perform_async(args) を呼び出したとき
  • 特徴: 同期的な処理で、JobをRedisに保存するだけ

2. Redis

  • 役割: ジョブキューの保存場所
  • 特徴:
    • メモリ上にデータを保存して高速アクセス(NoSQL)
    • Jobを永続化するために利用
    • Active Jobのデフォルトのインメモリストレージと違い、サーバー再起動後もジョブが失われない

3. Sidekiq Server (Worker)

  • 役割: ジョブを実行する
  • 動作場所: 独立したプロセスとして(bundle exec sidekiq で起動)
  • 特徴: Redisからジョブを取り出し、対応するWorkerクラスの処理を実行

実際の処理フロー

  1. Railsアプリ(Sidekiq Client)がSomeWorker.perform_async(1, 2) を呼び出す
  2. Sidekiq Clientがジョブ情報をシリアライズしてRedisに保存
  3. Sidekiq Server(別プロセス)がRedisをポーリングし、ジョブを発見
  4. Sidekiq Serverがジョブを取り出し、指定されたWorkerクラスのメソッドを実行

Sidekiqを使うべき場面

1. まとめて処理する場合(大量データの一括処理)

:

  • 管理画面からCSVファイルをアップロードしてマスタデータを作成
  • ECサイトで10万件の商品データをCSVからインポート
  • 1年分の売上データを分析してレポート生成

メリット:

  • ユーザーは処理完了を待たずに他の作業を続けられる(UX向上)
  • 処理中にエラーが発生しても再試行できる
  • サーバーがクラッシュしても処理は失われない

2. 定期実行が必要な場合

軽量な処理の場合:

  • whenever gem + cron で十分

複雑・重い定期処理の場合:

  • Sidekiq + Sidekiq-Scheduler/Sidekiq-Cron を使用
  • 例:ECサイトの日次・週次・月次の複合的なアナリティクスデータ集計

Docker環境でのSidekiq運用

Docker環境でRailsアプリケーションとSidekiqを使用するときのcompose.yml。Sidekiqの使用例としては、管理画面からマスターデータのCSVファイルをアップロードしてデータベースに保存するとする

この時、appコンテナ (Railsアプリ)は、Sidekiq ClientとしてJobをRedisにキューイングする役割を持っているので、redisコンテナが先に起動している必要がある

また、sidekiqコンテナは、RedisからJobを取り出してデータベースに保存する処理 (Workerクラスに定義) を担うので、redisコンテナとdbコンテナが先に立ち上がっている事を保証する必要がある

# compose.ymlservices:app:image: your-rails-appdepends_on:db:condition: service_healthyredis:condition: service_healthy # ...その他の設定db:image: mysql:8.0volumes:-mysql_data:/var/lib/mysqlhealthcheck:test:["CMD","mysqladmin","ping","-h","localhost"]interval: 5stimeout: 5sretries:5 # ...その他の設定redis:image: redis:7.0volumes:-redis_data:/datacommand: redis-server --appendonly yeshealthcheck:test:["CMD","redis-cli","ping"]interval: 5stimeout: 3sretries:5 # ...その他の設定sidekiq:image: your-rails-appcommand: bundle exec sidekiqdepends_on:db:condition: service_healthyredis:condition: service_healthyvolumes:mysql_data:redis_data:

Redisデータの永続化

Redisコンテナのデータを永続化するには、以下の2つの方法がある

1. ボリューム (Volumes)

volumes:-redis_data:/data
  • Dockerが管理する専用の場所にデータを保存
  • 複数コンテナ間で共有可能
  • バックアップやマイグレーションが容易

2. バインドマウント (Bind Mounts)

volumes:-./redis-data:/data
  • ホストマシン上の特定パスをコンテナにマウント
  • ホスト側のファイル変更がすぐにコンテナに反映される

注意点

  • アプリ、Redis、DBなど全てのコンテナが立ち上がっている状態でSidekiqコンテナを起動する必要がある
  • Redisコンテナは再起動するとデータが消えるため、DBコンテナ同様にvolumeを設定して永続化する

まとめ

バックエンド側での非同期処理についてあまりイメージがついていませんでしたが、Sidekiqを使うことで、重い一斉メール送信やCSVインポートなどの処理を非同期で実行できて、また、複雑な処理の定期実行などもできるみたいです

参考資料

qiita.com

zenn.dev

qiita.com

画像データの効率的保存方法

画像データの保存場所

別テーブルでの保存

多くのシステムで画像を別テーブルに保存する理由:

  • パフォーマンス向上: メインのデータと画像データを分離することで、通常のクエリでは画像データを読み込まない
  • スケーラビリティ: 画像のようなバイナリデータは肥大化しやすく、別テーブルにすることでメインテーブルのサイズを抑制できる
  • 多対多の関係: 一つのエンティティに複数の画像が関連する場合や、画像が複数のエンティティで共有される場合

データベース外での保存

実際のベストプラクティスとしては、画像データ自体はデータベースではなく専用のストレージに保存することが一般的

この場合、データベースには画像への参照情報(パスやURL)のみを保存します。

画像データの保存形式

バイナリデータ(BLOB)としての保存

データベースにバイナリデータとして保存する場合:

  • メリット: 追加のエンコード/デコードが不要で効率的
  • デメリット: 一部のDBMSでは大きなBLOBの処理に制限がある

Base64エンコードした文字列としての保存

Base64エンコードしてテキストとして保存する場合:

  • メリット: テキストベースのデータとして扱えるため汎用性が高い
  • デメリット: データサイズが約33%増加し、エンコード/デコードのオーバーヘッドがある

業界での一般的なプラクティス

最も広く採用されているアプローチは以下の2パターン

  1. 画像データはデータベース外のストレージに保存

    • S3などのオブジェクトストレージサービス
    • CDNと組み合わせてパフォーマンスを向上
  2. データベースには参照情報のみを保存

    • 画像へのURL/パス
    • メタデータ(サイズ、ファイル形式、作成日時など)

このアプローチは以下のメリットがある

  • データベースのサイズを適切に保つ
  • バックアップと復元が簡単
  • スケーラビリティの向上
  • 読み込みパフォーマンスの向上(特にCDN使用時)

小規模なアプリケーションや特殊な要件がある場合を除き、画像データの保存には専用のストレージソリューションを使用するのが現代のベストプラクティスと言える

検索
リンク

引用をストックしました

引用するにはまずログインしてください

引用をストックできませんでした。再度お試しください

限定公開記事のため引用できません。

読者です読者をやめる読者になる読者になる

[8]ページ先頭

©2009-2025 Movatter.jp