[Redis]Django-Q2のブローカーをRedisの変更

TIPS
TIPSツール

現在のコードを書き換えることなく、ブローカー(キューの保存先)だけを SQLite から Redis へ差し替える手順です。

これにより、SQLiteの「database is locked」問題が完全に解消され、メモリ消費も最小限に抑えられます。

ステップ1:Redis本体のインストール

まずはホストOS(Ubuntu)にRedisサーバーをインストールして起動します。

sudo apt update
sudo apt install redis-server -y
sudo systemctl enable --now redis-server

ステップ2:PythonのRedisライブラリをインストール

仮想環境に入り、django-q2 が Redis と通信するためのライブラリをインストールします。

# 仮想環境を有効化(パスはご自身の環境に合わせてください)
source /venv/bin/activate

# redisパッケージをインストール
pip install redis

ステップ3:Django側の設定(settings.pyの修正)

プロジェクトの settings.py を開き、Q_CLUSTER の設定を書き換えます。

SQLiteを使用する設定('orm': 'default')を削除し、redis の接続情報を追記します。

Q_CLUSTER = {
    \'name\': \'q_cluster\',
    \'workers\': 2,            # CPUコア数やメモリに合わせて2〜4程度に制限(重要)
    \'recycle\': 500,          # メモリリーク防止のため、500回タスクを処理したらワーカーを再起動
    \'timeout\': 60,           # タスクのタイムアウト(秒)
    \'retry\': 120,            # 失敗時の再試行までの時間(秒)
    \'queue_limit\': 50,       # メモリに展開するタスク数の上限
    \'bulk\': 10,              # 一度に処理するタスク数
    
    # ここから下がRedisブローカーの設定(\'orm\': \'default\' は削除すること)
    \'redis\': {
        \'host\': \'127.0.0.1\',
        \'port\': 6379,
        \'db\': 0,             # データベース番号(0〜15)
        \'password\': None,
        \'socket_timeout\': None
    }
}

ステップ4:孤児プロセスの完全キル(超重要)

現在裏で暴走している古いクラスター群を、OSレベルで一度すべてキルします。これをやらないと、古いプロセスがいつまでもSQLiteを見に行ってしまいます。

sudo pkill -f qcluster

# 何も表示されなければ全員死んでいます
ps -ef | grep qcluster

ステップ5:Systemdサービスファイルの修正(孤児化対策)

前回の暴走を二度と起こさないため、Systemdのサービスファイル(例: /etc/systemd/system/q-qcluster.service など)を開き、[Service] セクションに KillMode=mixed を追記します。

[Unit]
Description=Django-Q2 Worker
After=network.target redis-server.service

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/q-tools
ExecStart=python manage.py qcluster

# ===== 孤児プロセスを許さない設定 =====
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=10
# ======================================

Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

ステップ6:反映と起動確認

Systemdの設定をリロードし、ワーカーを起動します。

sudo systemctl daemon-reload
sudo systemctl restart q-qcluster.service

起動したら、正しくRedisに繋がってタスクを待機しているか、以下のコマンドでモニター画面を開いて確認します。

python manage.py qmonitor

エラーが出ず、プロセス数が settings.py で設定した workers の数(上記設定なら親1つ、ワーカー2つなど)で安定していれば、Redisへの完全移行は成功です。

Q よくある質問 (FAQ)
Q. なぜDjango-Q2のブローカーをSQLiteからRedisに変更する必要があるのですか?
A.
SQLiteでは同時書き込み時に「database is locked」エラーが発生しやすいため、インメモリデータストアであるRedisに移行することで、この問題を解消し高速かつ安定したタスク処理を実現できます。
Q. 移行時に古いプロセス(孤児プロセス)をキルしなければならないのはなぜですか?
A.
古いプロセスがバックグラウンドで生存し続けていると、設定変更後も古いSQLiteデータベースを参照し続け、タスクの重複実行やエラーの原因になるため、OSレベルで完全にキルする必要があります。
Q. Systemdの「KillMode=mixed」を設定する理由は何ですか?
A.
Systemdがサービス停止時に親プロセスだけでなく、Django-Q2のワーカープロセス(子プロセス)も確実に同時に終了させ、プロセスの孤児化や暴走を防ぐためです。

コメント

タイトルとURLをコピーしました