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

私と私の猫の他は誰でも隠し事を持っている

野良プログラマ発、日々のアウトプット

Redis で FIFO バッファを作って PHP から使う

昨今じゃ当たり前になった NoSQL ってやつですが、自分はどうも使う機会が無かったというか、フツーに RDB 使ったほうが目的に叶うケースが多かったので memcached でさえ殆ど手を触れずに今日まで来ました。それがやっと先ごろ、NoSQL なシチュエーションが発生!という訳で、人生初 NoSQL の作業メモです。

要件は、各所から発生するデータをそのまま RDB に書き込むと諸事情で色々と嬉しくないので、いったんバッファに溜めておいて専用のデータストア用プログラム経由で逐次 RDB に格納するというものです。古いものから順に読み出す必要があるので、所謂 FIFO (First In First Out) バッファですな。memcached は万一のデータ消失が怖いので、最近評判が良いらしい Redis を採用。

まずは環境づくりから。当方の AWS EC2 な LAMP サーバにて、Redis を PHP から使えるようにします。Redis 関係は EPEL リポジトリにしか無いようなので、それを指定して yumインスコします。

% sudo yum --enablerepo=epel -y install redis

Redis サーバを起動して、ブート時の設定も忘れずに。

% sudo service redis start
% sudo chkconfig redis on

で、動作確認…

$ redis-cli
redis 127.0.0.1:6379> info
redis_version:2.4.10
(省略)
redis 127.0.0.1:6379> exit

よし、OK。

PHP の Redis 用モジュールのほうも同様にインスコ

% sudo yum --enablerepo=epel -y install php-pecl-redis
% sudo service httpd reload

以上で環境が整ったので、プログラムを書きます。Redis は色々なデータ型が用意されていますが、FIFO バッファは Lists 型を使って実現できるとここにあったので、これに倣って LPUSH で書き込み、RPOP で読み出すことにします。RDB 用のデータを Redis に書き込む側はこんな感じ。

$data = array(':name' => $name, ':email' => $email, ':created' => date('Y-m-d H:i:s')); //テーブル列名 => 値、な1レコードぶんのデータ
$redis = new Redis();
$redis->connect('localhost');
$redis->lPush('mykey', json_encode($data)); //JSON に変換して Redis に保存

Redis → RDB の処理側はこんな感じ。

$redis = new Redis();
$redis->connect('localhost');
$pdo = new PDO('mysql:host=localhost;dbname=my_db', 'login_name', 'login_pw');
$stmt = $pdo->prepare('INSERT INTO my_table (name, email, created) VALUES (:name, :email, :created)');
while ($data = $redis->rPop('mykey')) { //有るだけ読み出しては RDB に追加
	$data = json_decode($data, true);
	$stmt->execute($data);
}

とまぁ、こんな具合です。実にシンプルな利用ケースなので一寸物足りない気もw 他のデータ型も使ってみたいなー。