じつは自宅サーバのロードアベレージが上がり続けています。分析の結果、ボトルネックは I/O 処理でした。CPU は Athlon64 X2 4400+ ですが、まだまだ当分この CPU で間に合いそうです。HDD は当時は 7200 回転で最速だった HITACHI Deskstar T7K250 SATA2 250GB を RAID1 構成にしたのですが、今思えば速度優先で RAID0 にしておけば良かったと少しだけ後悔。

I/O がボトルネックに成っている理由ですが、Drk7jp が公開しているサービスの全てがキャッシュファイルを利用した高速化手法を取っているのですが、単純にそれらファイルの write 処理が追いついていません。常に何らかのプロセスで I/O 待ち状態が発生しているような状況です。抜本的な解決方法としては disk を高速なものに交換する以外ありません。

というわけで、高速な SSD × ３本くらいで RAID0 構成で disk を再構築が将来の夢

ですが、まだまだ SSD の速度と価格を考えると買い時ではないので、延命措置を考えてみました。残る I/O パフォーマンスの向上は、本当はやりたくなかったのですが、ext3 のジャーナリングモードの変更による高速が残してありました。

ext3 のジャーナリングモード変更についてまとめます。

- スポンサーリンク -

手順を書く前に、ジャーナリングモードを変更することで本当に I/O 性能が改善するか？という疑問に対する１つの参考例のご紹介です。個人的にはどこかに導入したくてたまらない memcached 並に高速でありながらファイル上にデータを記録して永続化することができる Tokyo Tyrant についての記事です。

mixi Engineers’ Blog » Tokyo Tyrantによる耐高負荷DBの構築

近頃の有名Linuxディストリビューションの標準ファイルシステムであるEXT3では、writeの頻度が高いとジャーナリングのために性能が極端に悪くなるという問題があります。試しにデフォルト設定のEXT3でTTを動かしてみたところ、8000QPSくらいで頭打ちになってしまいました。

EXT2を使えばこの問題は起きないのですが、EXT3でも対処することはできます。EXT3にはデフォルトのorderedモードの他に、堅牢性重視のjournalモードと、高速性重視のwritebackモードがあります。このうちで、writebackモードを使うのです。また、readが発生する度にファイルの最終アクセス時刻のメタデータが更新されるのを防ぐために、noatimeオプションもつけます。fstabの設定は以下のようになります。

LABEL=/hoge /hoge ext3 rw,noatime,data=writeback 1 2

これらをやるだけでTCおよびTTのパフォーマンスは3倍くらいになり、晴れて実運用の要件を満たすことができました。

というわけで mixi の TT やってる技術者が検証をとっていると言うことで、性能改善があることをまずは信じてみることにして、ジャーナリングモードを writeback に変更することにしました。

ジャーナリングモードの変更の手順

0. まずは現状の mount 状態の確認

$ sudo mount /dev/md2 on / type ext3 (rw,noatime) none on /proc type proc (rw) none on /sys type sysfs (rw) none on /dev/pts type devpts (rw,gid=5,mode=620) usbfs on /proc/bus/usb type usbfs (rw) /dev/md0 on /boot type ext3 (rw) none on /dev/shm type tmpfs (rw,noatime) none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw) sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)

じつは既に noatime 設定は実施済みなのですが、write には全然効果はありませんでした。resad は多少高速化されました。

1. grub の変更。ルートのジャーナリングモードを変更する

当システムでは、ディスクを３つのパーティションに分けていて /, /boot, swap の構成になっています。本当は CGI のファイルキャッシュ用にパーティションが作ってあって、そこだけ writeback が最適解なのですが、残念ながらすべて / （ルート）配下で管理する構成なので、grub の設定を変更する必要あり。ちなみに Cento OS 環境です。

kernel の起動オプションとして rootflags=data=writeback を追加します。

$ sudo vi /boot/grub/menu.lst ・・・略・・・ title CentOS (2.6.9-55.ELsmp) root (hd0,0) kernel /vmlinuz-2.6.9-55.ELsmp ro root=/dev/md2 rhgb quiet rootflags=data=writeback initrd /initrd-2.6.9-55.ELsmp.img ・・・略・・・

2. fstab を編集してマウント時に writeback オプションを有効にする。

ここも自分の環境に合わせて設定を適宜変更する。設定を変更したいデバイスの行のマウントオプションとして、defaults の後ろに ,noatime,data=writeback を追加します。

$ sudo vi /etc/fstab /dev/md2 / ext3 defaults ,noatime,data=writeback 1 1 /dev/md0 /boot ext3 defaults 1 2 ・・・略・・・

3. writeback オプションを適用して、各ファイルシステムの属性を変更する。

実行に時間がかかると思いきや、１秒もかからなかった。

$ sudo tune2fs -o journal_data_writeback /dev/md2

4. 再起動

$ sudo reboot

5. 設定確認

再起動後に writeback でマウントされているかを確認する。writeback と表示されれば成功！

$ mount /dev/md2 on / type ext3 (rw,noatime,data=writeback) none on /proc type proc (rw) none on /sys type sysfs (rw) none on /dev/pts type devpts (rw,gid=5,mode=620) usbfs on /proc/bus/usb type usbfs (rw) /dev/md0 on /boot type ext3 (rw) none on /dev/shm type tmpfs (rw,noatime) none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw) sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)



さて、ジャーナリングモードの変更の危険性もちゃんと明記しておかないといけないので、ext3 の３つのジャーナリングモードについてまとめます。マニュアルより抜粋。

data=journal



メインファイルシステムより前に、全てのデータがジャーナルに記録される。

デフォルト。メタデータがジャーナルに記録される前に、全てのデータがメインファイルシステムに直接書き出される。

データの順番は保存されない。メタデータがジャーナルに記録された後で、データがメインファイルシステムに書き込まれる。これはスループットを高くするオプションらしい。このオプションは内部ファイルシステムの完全性を保証する。しかし、クラッシュした後のジャーナルによる回復で、ファイルが昔のデータになることも許されている。

data=ordereddata=writeback

つまり、data=writeback によるジャーナリングはシステムが停電や電源プチッって場合にはタイムスリップしてしまう可能性が大いにあるというわけです。したがって、僕も本当はキャッシュファイル用のパーティションを作ってそこだけ writeback 設定にしたかったので最後の最後までこの技を残しておいたわけですが、先日 UPS も購入して不慮の事態時にも手動でシステム停止するくらいの時間がとれるようになったので、writeback はありかと思った次第です。

設定を変更して約３０分経ちましたが MTRG で計測している I/O の write の性能が劇的に改善されました。今日一日様子を見てグラフは再アップします。

__追記__

リクエスト数が減っていないけど、I/O 性能が向上していることが確認できました。ジャーナリング周りの性能改善ということなのでしょう。多分。改善されたのでこれ以上解析しません。

トラフィック（≒リクエスト数）

ロードアベレージ（×１００倍スケールで表示）

I/O 性能（/proc/diskstats より）





- スポンサーリンク -