Perl Hackers Hub

第10回 ジョブキューで後回し大作戦―TheSchwartz,Qudo,Q4M(3)

この記事を読むのに必要な時間:およそ 4 分

Q4M―MySQLを利用したジョブキュー

今まではPerlで作られたミドルウェアとしてのジョブキューを紹介してきましたが,最後にMySQLのプラグインとして提供されるジョブキューQ4Mを紹介します。Q4Mは本連載第6回UNIXプログラミングの勘所を執筆した奥一穂氏によって作られています。MySQLには依存してしまいますが,利用するプログラミング言語には依存しません。MySQLに接続できるどのプログラミング言語からも利用できます。また,TheSchwartzやQudoのようにミドルウェア側のデータスキーマの制限を受けることがないのも魅力の一つでしょう。

Q4Mの使い方

Q4Mのインストール方法はドキュメントで確認してください。

Q4Mをインストールしたら次はジョブキューで使用するテーブルを定義します。TheSchwartzやQudoでは決められたテーブル定義を使用する必要がありましたが,Q4Mは好きなテーブルを定義し利用できます。今回は次のようなテーブルを定義したものとします。

CREATE TABLE welcome (
    nickname       varchar(255) NOT NULL,
    email          varchar(255) NOT NULL,
    created_on int(10) unsigned NOT NULL
) ENGINE=QUEUE DEFAULT CHARSET=utf8;

通常のテーブル定義と異なるのはENGINEにQUEUEを使っている点です。Q4MをMySQLにインストールするとQUEUEエンジンが利用できるようになり,このエンジンで定義されたテーブルを使うことでジョブキューを管理できるようになります。

ジョブの登録

TheSchwartzやQudoではジョブの情報をシリアライズしてデータベースのカラムに格納していましたが,Q4Mでは自由なテーブル定義を行うことができるのでシリアライズを考える必要がありません。ジョブを登録するには,INSERTでレコードを登録するだけです。

mysql> INSERT INTO welcome(nickname,email,created_on)
VALUES('nekokak','nekokak@gmail.com',UNIX_TIMESTAMP());

登録したジョブは,通常のMySQLのレコードと同様にSELECT文を使うだけで参照できます。

mysql> SELECT * FROM welcome;
+----------+-------------------+------------+
| nickname | email             | created_on |
+----------+-------------------+------------+
| nekokak  | nekokak@gmail.com | 1307539020 |
+----------+-------------------+------------+

実際のアプリケーションではDBIを使ってwelcomeテーブルにINSERTを実行します。

#! /usr/bin/perl
use strict;
use warnings;
use DBI;

my $dbh = DBI->connect('dbi:mysql:q4m_test','root','');
$dbh->do(q{
    INSERT INTO welcome(nickname,email,created_on)
    VALUES(?,?,UNIX_TIMESTAMP())
}, undef, 'nekokak', 'nekokak@gmail.com');

ジョブの取り出し

次にジョブを取得します。ジョブを取得するにはqueue_waitというfunctionに,対象となるキューテーブル名を指定しSELECTを実行します。

mysql> SELECT queue_wait('welcome');
+-----------------------+
| queue_wait('welcome') |
+-----------------------+
|                     1 |
+-----------------------+

成功すると結果として1が返ってきます。この状態をオーナーモードと呼びます。オーナーモード中に対象テーブルをSELECTすると1レコードだけ取得できるようになります。

mysql> SELECT * FROM welcome;
+----------+-------------------+------------+
| nickname | email             | created_on |
+----------+-------------------+------------+
| nekokak  | nekokak@gmail.com | 1307539020 |
+----------+-------------------+------------+

ジョブの終了

ジョブワーカはこれで取得できた情報をもとに処理を実行します。ジョブワーカの処理が正常に終了したらキューを終了させるコマンドを実行します。

mysql> SELECT queue_end();
+-------------+
| queue_end() |
+-------------+
|           1 |
+-------------+

これにより同時にジョブレコードが削除され,オーナーモードが解除されます。もしジョブワーカの処理が異常終了した場合は,

mysql> SELECT queue_abort();
+---------------+
| queue_abort() |
+---------------+
|             1 |
+---------------+

を実行することでオーナーモードを解除します。queue_abort()した場合はジョブレコードは削除されずそのままデータベースに残ります。基本的にはこの繰り返しでジョブを処理するプログラムを自分で書きます。自分で書くと言うと難しく感じますが,基本的にはSQLのINSERTやSELECTを実行するだけなので,難しいものではありません。

Q4Mを使った簡単なサンプルプログラムは次のようになります。

#! /usr/bin/perl
use strict;
use warnings;
use DBI;

my $dbh = DBI->connect('dbi:mysql:q4m_test','root','');
while (1) {
    my $lock = $dbh->do("SELECT queue_wait('welcome')")
    if ($lock) {
        my $queue = $dbh->do('SELECT * FROM welcome');
        # ここでジョブの処理をさせる
        $dbh->do('SELECT queue_end()');
    }
}

ジョブのロック時間の調整

queue_waitを実行するときの第2引数で,ジョブをロックするまでの待ち時間を秒単位で決めることができます。

mysql> select queue_wait('welcome',10);
+--------------------------+
| queue_wait('welcome',10) |
+--------------------------+
|                        0 |
+--------------------------+

指定秒数内にキューからデータを取得できない場合は,諦めて処理を中断することもできます。

著者プロフィール

小林篤(こばやしあつし)

株式会社ディー・エヌ・エー プラットフォームシステムグループに所属。Mobagae APIやGadget Serverを担当。

「YAPC::Asia」や「Yokohama.pm」などでスピーカーをするなど,Perl関連のコミュニティへ積極的に参加している。YAPC::Asia2010ではベストスピーカ賞(次点)受賞。

CPANモジュールに「DBIx::Skinny」「Teng」「Qudo」など多数。

ネコが大好きだが,パグを2頭かってるプログラマ。

Twitter:@nekokak

Blog:http://blog.nekokak.org/

コメント

コメントの記入