ライブドア製のレコメンデーションエンジン cicindela を CentOS 5.4 にインストールした記録です。極力 yum/rpm によるインストールを行うようにしています。参考にさせていただいたサイトははてブのcicindelaタグにまとめておきます。
cicindela ソースコードのチェックアウト
Google Code でホストされている cicindela 本体のソースコードを /home/cicindela にチェックアウト。ここは公式の手順と全く同じなので、そちらを参照のこと。
Perlモジュールのインストール
DBI/DBD-mysql は mysql-server を入れたら付いてくるので、その他のモジュールをrpmforgeから導入。公式サイトには書いていないが、私の環境では Class::Data::Inheritable と DBIx::ContextualFetch も必要だった。
sudo yum --enablerepo=rpmforge install \ perl-Ima-DBI \ perl-Time-Piece \ perl-Log-Log4perl \ perl-Module-Pluggable \ perl-Class-Singleton \ perl-Class-Data-Inheritable \ perl-DBIx-ContextualFetch
ここで次のようなエラーが出た。
/usr/share/man/man3/Sys::Syslog.3pm.gz from install of perl-Sys-Syslog-0.27-1.el5.rf.i386 conflicts with file from package perl-5.8.8-27.el5.i386
Log-Log4perl の依存パッケージとしてインストールされる perl-Sys-Syslog パッケージが、CentOS 5(RHEL5)標準の perl パッケージに含まれる Sys::Syslog のファイルと衝突するらしい。参考URL。 仕方がないので Log::Log4perl だけは cpan コマンドでインストールした。
sudo cpan -i Log::Log4perl
MySQL のインストールと設定
MySQL をインストール。
yum install mysql-server公式のインストールガイドには /home/cicindela/etc/mysql/my.cnf を /etc/my.cnf にコピーせよとあるが、この中にはかなり癖の強い設定が含まれているので、既存のサーバを流用する場合は要注意。というか、実質的には cicindela 専用サーバが必要になると考えた方が良いだろう。
特に注目すべき設置項目は以下の4つ。
- max_heap_table_size = 1024M
- MEMORY テーブルの最大サイズ。cicindela は MEMORY テーブルに入力データを保存するため、それなりに大きなサイズが必要になる。実際のところ、どのくらいあれば十分と言えるのだろうか…。
- innodb_log_file_size = 256M
- この設定値を後から変更すると起動不能に陥る場合があるので注意。変更する場合はこちらのサイトを参考に。
- innodb_lock_wait_timeout = 1800
- デッドロックと判断するためのタイムアウト。デフォルトは50秒なので、極端に長い。おそらくはバッチ処理の都合でこうなっているのだろう。
- innodb_flush_log_at_trx_commit = 2
- この設定値がどの程度意味を持つものなのか、正直言って分からない。MySQLリファレンスによれば、値を2にすることで、『より良い性能』と引き換えに『OS のクラッシュか停電によって、最後の秒のトランザクションが消されてしまいます。 』とのこと。
cicindela 用データベースの作成
misc/create_init_sql.pl を実行して、DB初期化用SQLを生成する。このスクリプトで生成できるのは CREATE DATABASE文、CREATE TABLE文 さらに –grant_* オプションを指定することで GRANT文も生成できる。
cd misc perl create_init_sql.pl --db_name=cicindela \ --grant_user=cicindela \ --grant_host=localhost \ --grant_pass=cicindela_pass | mysql -uroot
cicindela の設定
cicindela の設定ファイル lib/cicindela/lib/Cicindela/Config/_common.pm の中で最小限の設定を含む集計セットを定義する。ここでは pick という名前にした。datasource に指定するDB名やhost名は適宜変更のこと。
$C{SETTINGS} = { 'pick' => { datasource => [ 'dbi:mysql:cicindela;host=localhost', 'cicindela', 'cicindela_pass' ], filters => [ 'PicksExtractor', 'InverseUserFrequency', 'ItemSimilarities', ], recommender => 'ItemSimilarities', refresh_interval => 1, }, };
設定を変更したらApacheを再起動。error_log や logs/log.txt にエラーが出ていないことを確認しておく。
動作確認
以下のようなURLにアクセスして、HTTPステータスコード204が返ることを確認。user_id や item_id を変えつつ何度かアクセスしておく。
http:///cicindela/record?set=pick&op=insert_pick&user_id=3&item_id=23
入力バッファテーブルにデータが入っていることを確認。
mysql> select * from picks_buffer; +----+---------+--------------+---------+--------------+-----------+---------------------+ | id | user_id | user_char_id | item_id | item_char_id | is_delete | timestamp | +----+---------+--------------+---------+--------------+-----------+---------------------+ | 1 | 3 | NULL | 23 | NULL | 0 | 2009-12-25 17:28:03 | | 2 | 3 | NULL | 23 | NULL | 0 | 2009-12-25 17:28:11 | | 3 | 3 | NULL | 23 | NULL | 0 | 2009-12-25 17:28:29 | | 4 | 3 | NULL | 23 | NULL | 0 | 2009-12-25 17:28:52 | | 5 | 5 | NULL | 23 | NULL | 0 | 2009-12-28 13:24:00 | | 6 | 5 | NULL | 29 | NULL | 0 | 2009-12-28 13:24:20 | +----+---------+--------------+---------+--------------+-----------+---------------------+ 6 rows in set (0.01 sec)
手動で bin/flush_buffer.pl を実行。
./bin/flush_buffer.pl
入力バッファがクリアされ、一時データテーブルに入力されることを確認。
mysql> select * from picks_buffer; Empty set (0.00 sec) mysql> select * from picks; +---------+---------+---------------------+ | user_id | item_id | timestamp | +---------+---------+---------------------+ | 3 | 23 | 2009-12-25 17:28:03 | | 5 | 23 | 2009-12-28 13:24:00 | | 5 | 29 | 2009-12-28 13:24:20 | +---------+---------+---------------------+ 3 rows in set (0.00 sec)
次に bin/batch.pl を実行、集計結果を算出する。初回実行時には2回実行する必要がある。ある程度以上のデータが溜まっていないと算出されないので注意。
./bin/batch.pl
mysql> select * from item_similarities_online; +----------+----------+------------------+ | item_id1 | item_id2 | score | +----------+----------+------------------+ | 23 | 25 | 1.58496250072116 | | 25 | 23 | 0 | +----------+----------+------------------+ 2 rows in set (0.00 sec)
最後に以下のようなURLにアクセスして、Web API経由でリコメンデーション・データを取得できることを確認。
http:///cicindela/recommend?set=pick&op=for_item&item_id=23
以上で cicindela の最低限の動作は確認できた。
daemontools のインストール
次に flush_buffer.p と batch.pl の実行を自動化するため、daemontools をセットアップする。まず daemontools-toaster のSRPMを http://www.qmailtoaster.org/ から取得して、ビルド&インストール。
rpmbuild --rebuild daemontools-toaster-0.76-1.3.6.src.rpm rpm -Uvh daemontools-toaster-0.76-1.3.6.$ARCH.rpm
cicindela のバッチスクリプトに対するシンボリック・リンク作成。
sudo ln -s /home/cicindela/etc/service/cicindela_batch /service/ sudo ln -s /home/cicindela/etc/service/cicindela_flush_buffers /service/
/etc/inittab の末尾に svscan の起動コードを追加。
SV:123456:respawn:/command/svscanboot
init に HUP シグナルを送ってinittabを読み込み直し、svscanを起動する。
sudo kill -HUP 1
ps コマンド等で svscan, supervise プロセスが起動していることを確認しておく。
この状態でもう一度データの入力テストを行い、自動的に一次データ・計算結果が更新されることを確認。
このまま放っておくとどんどんログが肥大化していくので、ログローテーション用設定ファイル /etc/logrotate.d/cicindela を以下の内容で作成する。
/home/cicindela/var/logs/log.txt {
daily
create 0666 root root
rotate 2
}
次はより実践的な構成でテストを行う予定。