« 2007年12月 | メイン | 2008年02月 »

2008年01月30日

setlock を使って cron をぶんまわす方法

 事前計算や DB 再構築を手軽に実行するのに cron は便利ですが、タスクのまわし過ぎによるサービスのパフォーマンス低下や実行順序の制御を別途行う必要があります。自分は、そのためのツールとして、daemontoolssetlock コマンドがお気に入りです。setlock は、flock を用いて、タスクの待機や実行中止を制御することのできる、とても小回りのきくプログラムです。

1-59/* * * * * /usr/local/bin/setlock -nx /tmp/precompute.lock /usr/local/bin/setlock /tmp/allcron.lock precompute --mode=minutely
0 1-23/* * * *      /usr/local/bin/setlock /tmp/precompute.lock /usr/local/bin/setlock /tmp/allcron.lock precompute --mode=hourly
0 0 * * *      /usr/local/bin/setlock /tmp/precompute.lock /usr/local/bin/setlock /tmp/allcron.lock precompute --mode=daily && /usr/local/bin/setlock /tmp/allcron.lock rebuild_db

 たとえば、上の cron は、以下のようなことを実現しています。

  • 毎分1回、前回の処理が完了している場合のみ、毎分行うべき事前計算処理 (precompute --mode=minutely) を行う
  • 毎時1回、毎時必ず行うべき事前計算処理 (precompute --mode=hourly) を行う
  • 毎日1回、毎日必ず行うべき事前計算処理 (precompute --mode=daily) を行う
  • 毎日1回、日次の事前計算処理の完了後に、データベースの再構築 (rebuild_db) を行う
  • これらのタスクは、すべて順列化されて実行され、同時に複数が動作することはない

 最近はマルチコア環境が一般化しつつあるので、処理が CPU インテンシブな場合は、このようにして特定のCPUコアをバックグラウンドタスクに張り付けるというアプローチも可能です。また、HDD やメモリのバンド幅が問題になる場合は、それぞれのタスク内で sleep させることで、負荷の調節が可能です。DBIx::Replicate には、そのような仕組み (load アトリビュート) が入っています。

投稿者 kazuho : 2008年01月30日 11:08 | トラックバック (0) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

2008年01月29日

データベースをコピーするモジュール DBIx::Replicate

 データベースをオンデマンドでコピーするモジュール DBIx::Replicate を書いて、CodeRepos にアップロードしました。こんな感じで使います。

use DBIx::Replicate qw/dbix_replicate/;

# 20才以下の人だけを young_table にコピー (1000行毎, 最大負荷 0.5)
dbix_replicate({
    src_conn     => $dbh,
    src_table    => 'all_people',
    dst_conn     => $dbh,
    dest_table   => 'young_people',
    primary_keys => [ qw/id/ ],
    columns      => [ qw/id name age/ ],
    block        => 1000,
    load         => 0.5,
    extra_cond   => 'age<20',
});

# zipcode 毎にクエリを分割してテーブル全体をコピー
dbix_replicate({
    src_conn     => $src_dbh,
    src_table    => 'tbl',
    dest_conn    => $dest_dbh,
    dest_table   => 'tbl',
    copy_by      => [ qw/zipcode/ ],
});

 1回のクエリで転送する量を行数あるいはカラムの値で制限することができるので、テーブルをダンプしての転送やレプリケーションよりも柔軟な運用が可能かと思います。もちろん、コピーできるテーブルの大きさに制限もありません。たとえば、以下のような場合に便利かもしれません。

  • 異なるRDBMS間でデータをコピーしたい
  • インクリメンタルコピーでいいから、転送中に発生するロックを最小限にしたい
  • 絞り込みを行いつつデータをコピーしたい
  • InnoDB を使っているが mysqldump --single-transaction | ssh mysql 等だとメモリ負荷が大きい

 現状の問題としては、以下のようなものがあります。

  • トランザクションを使っているので MyISAM のコピーには使えない
  • MySQL は delete の条件節内の (min_a,min_b)<=(a,b) and (a,b)<(max_a,min_b) をrangeクエリに最適化してくれないので、複合プライマリキーをコピーする場合には、上の使用例の下のタイプである copy_by を使う必要がある

といったあたりです。もともと手元で動かしていたものを、ユニットテストを書きたくなったがために分割してモジュール化したので ad-hoc なコードですがご容赦いただければ。誰か OO な設計にリファクターして、いろんなコピー戦略を実装できるようにしてくれないかなぁ。

投稿者 kazuho : 2008年01月29日 16:03 | トラックバック (1) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

2008年01月22日

Pathtraq リニューアルのおしらせ (リアルタイム検索機能の追加ほか)

 Pathtraq は、ウェブブラウザの拡張機能を通してアクセス情報を匿名化・統計処理することにより、ウェブ上の人気ページや注目のサイトを発見するシステムです。公開より5ヶ月、多くの方々に拡張機能をインストールしていただき (ありがとうございます)、統計として様々な見せ方をできる準備が整ってきたように思います。そこで今回、より便利にお使いいただけるよう、デザインのリニューアルと新機能の追加を行いました。

1. デザインのリニューアルについて

 ウェブサイトのデザインを全面的に見直しました。今、何が話題になっているのかがよりわかりやすく、また、どのように活用できるかが、フレンドリーに伝わるようになったと思います。

2. 検索機能の追加について

 従来から存在する検索エンジンの多くは、情報の「資料性」を重視しています。例えば Google で「自民党」を検索すると、党に関する基本的な情報が上位に表示されますが、党内外で、今、何が起こっているのかは、ほとんど表示されません。一方、「資料性」ではなく「時事性」を重視する検索エンジンとしては、ニュース専門の検索エンジンやブログ専門のものが存在します。しかしこれらは、検索範囲が限定されたり、あるいはランキングアルゴリズムが貧弱で、注目情報が探しにくい、といった問題を抱えています。  今回 Pathtraq に追加した検索機能は、HTML の解析機能とリアルタイムのアクセス統計を組み合わせることで、キーワードがどのような理由で注目されているか、的確にランクづけして表示することを目標においています。まだまだチューニングは必要ですが、例にあげた「自民党」をはじめ、様々なキーワードでお試しいただければと思います。

続きを読む "Pathtraq リニューアルのおしらせ (リアルタイム検索機能の追加ほか)"

投稿者 kazuho : 2008年01月22日 13:04 | コメント (1) | トラックバック (0) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

2008年01月15日

Q4M - MySQL 上で動作するメッセージキュー

 数年来ずっと「RDBMSに統合されたメッセージキューがほしい」と言ってきたわけですが、昨年末にストレージエンジンをプラグインとして開発できる MySQL 5.1 が RC になっていることに気づき、自分で作ってみました。

Q4M (Queue for MySQL) は MySQL 5.1 のプラガブル・ストレージ・エンジンとして動作するメッセージキューであり、堅牢・高速・柔軟であるよう設計されています。昨年12月遅くに開発が開始され、まだ非常に原始的ですが、かなり高速に動作します。
q4m.31tools.com

 自分の英語を日本語訳するというのも変なものですが、ともかくそういったものです。なんだかんだ言っても、ちゃんとしたバイナリプロトコルの上に C + pthread で書かれたサーバなので、それなりに高速だと思います。ディスクに同期をとりつつパフォーマンスを稼ぐために必須の技術であるグループコミットも実装しましたし。

 Q4M は MySQL のストレージエンジンとして動作するので、MySQL に接続できるあらゆるプログラミング言語から利用することができます。また、Perl むけには、既に dmaki さんによって Perl 用のラッパーモジュール (Queue::Q4M) が開発されています。初回リリースですし、運用環境での使用をお薦めするものではありませんが、興味のある方はお試しいただければ幸いです。

PS. Q4M に興味をもたれた方で del.icio.us のアカウントをお持ちの方は、こちらからブックマークしていただければ幸いです。

投稿者 kazuho : 2008年01月15日 05:25 | トラックバック (1) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

2008年01月04日

ウェブアプリケーションにおけるHDDの正しい使い方

 データベース等のソフトウェアは一般に、停電やOSのクラッシュ時にデータが破壊されないよう、HDD へデータ保存が完了したか確認しながら処理を行うようになっています。その目的を果たすためにどのような API が OS によって提供されているか、少し勉強し直すことにしました。

 下表のうち、赤い部分がデータの永続性が保証されない危険な手法、青い部分が安全な手法です。したがって、各行において出来るだけ左側の (高速側の) 、そして言うまでもなく青い色の同期手法を使っていることが望ましいということになります。

OS openモード HDD または RAID 内の書込先
キャッシュ (高速) プラッター (低速)
Linux注1 同期 open(O_SYNC) fdatasync
非同期 N/A fdatasync
Linux+UPS注2
Linux+RAID注3
同期 open(O_SYNC) N/A
非同期 fdatasync N/A
Windows 同期 CreateFile(FILE_FLAG_WRITE_THROUGH) FlushFileBuffers
非同期 N/A FlushFileBuffers
Windows+UPS 同期 CreateFile(FILE_FLAG_WRITE_THROUGH) FlushFileBuffers
非同期 N/A FlushFileBuffers
Windows+RAID注3 同期 CreateFile(FILE_FLAG_WRITE_THROUGH) N/A
非同期 FlushFileBuffers N/A
Mac OS X 同期 N/A
非同期 fsync fcntl(F_FULLFSYNC)
Mac OS X+UPS 同期 N/A
非同期 fsync fcntl(F_FULLFSYNC)
Mac OS X+RAID注3 同期 N/A
非同期 fsync または fcntl(F_FULLFSYNC) N/A
Solaris 同期 open(O_SYNC) ioctl(DKIOFLUSHWRITECACHE)
非同期 fdatasync ioctl(DKIOFLUSHWRITECACHE)
Solaris+UPS 同期 open(O_SYNC) ioctl(DKIOFLUSHWRITECACHE)
非同期 fdatasync ioctl(DKIOFLUSHWRITECACHE)
Solaris+RAID注3 同期 open(O_SYNC) N/A
非同期 fdatasync または ioctl(DKIOFLUSHWRITECACHE) N/A

 実際に表を起こしてみて、以下のようなことがわかりました。

続きを読む "ウェブアプリケーションにおけるHDDの正しい使い方"

投稿者 kazuho : 2008年01月04日 16:13 | コメント (4) | トラックバック (0) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク