こんちは。開発2部の吉岡です。
ソーシャルゲームのサーバーで、陰ながら頑張ってくれるのがバッチサーバーです。
タスクを指定した時間か定期的に実行するサーバーになります。
バッチタスク管理daemon
処理としては、データベースに接続し、タスク溜め込み用のテーブルをチェックします。
そして、実行時間が過ぎているタスクがあれば、それを実行します。
最初にこの処理を作成した頃は、phpのdaemon用ライブラリを使用していたのですが、最新版では単純に無限ループをしています。
で、そのスクリプトをsupervisorで落ちないようにしています。
かなりざっくりと処理を書くと下のような感じです。
while( true ){ sleep(1); try{ $MasterDB = getDB('master'); $MasterDB->startTransaction();//トランザクションフラグを立てる //ジョブの取得(行ロックをかけて排他する) $newJob = LogicJob::getNewJob( $MasterDB ); //実行するジョブがなければ、continue if ( !$newJob ){ $MasterDB->close(); continue; } //ジョブの実行(execで別phpスクリプトを蹴る) LogicJob::execJob( $newJob ); //exec( $newJob['php_file'] . ' > /dev/null &' ); //ジョブステータスを実行中に変更 LogicJob::updateJobStatus( $MasterDB , $newJob, LogicDaemon::JOB_STATUS_EXEC ); //コミット $MasterDB->commit(); } catch( Exception $e ){ $MasterDB->rollback();//トランザクションフラグが立っていればrollback } $MasterDB->close(); }
タスクテーブルと行ロック
上のように実行すべきタスクがあるかチェックをするのですが、冗長化のため、この処理は複数のサーバーで走ることがあります。
同じテーブルのデータの取り合いになるので、ここで行ロックが必須となります。
この実装はなかなか苦労しましたが、現在は問題なく動作しています。
課題!
このバッチの実装は、ミドルウェアを使って、もっと高機能でカッコイイ感じにしたいんですが…
と、個人的には思います。
celerydとかどうなんでしょうか。pythonですが。
バッチサーバーの構築・運用、情報交換したいです!