天然パーマです。

Senna、MySQL 周りの「sugokuii beta」対処法的チューニング

昨日公開した「sugokuii beta」。 ある程度のトラフィックは予想していたものの、 深夜0時を超えた当たりから急に負荷が高くなった。 この深夜0時前後は魔の時間帯と俺は認識していて、 他に俺が運営しているムフフなサイトも23時頃からほんと急にアクセスが増える。 ただ今回の場合は尋常ではなかった。それもそのはず、 某人気おもしろ系ブログからリンクをしてもらったらしく、 いわゆる「スラッシュドット効果」が発生していたのだ。

スラッシュドット効果(スラド効果)、スラッシュドット現象(スラド現象)、Slashdot effectとは、あるウェブサイトがスラッシュドットに紹介されることで、そのサイトへのトラフィック(負荷)が爆発的に増え、サーバの限界を超えてしまうこと。一般的にウェブサイトに短期に爆発的にトラフィック(負荷)発生している状態だけを指すときもある。

スラッシュドット効果 - Wikipedia

ロードアベレージは20弱。上記のスラド現象に加え、今から考えると負荷に対しての「ずぼら」な作りのせいでなり負荷が高い。 ちなみにサーバーは ec2 の一番安い m1.small インスタンス一台ね。

そこで監視すると明らかに Senna を組み込んだ MySQL がボトルネックになっている。 というわけで、午前1時頃から Web アプリも含む以下の対処法的なチューニングを施し、 2時過ぎくらいにはやっと落ち着いてみれるようになので簡単に紹介。

my.cnf の設定を見直してキャッシュメモリを増やす。これは基本中の基本。 以下の DSAS のページが詳しいです。

それでも効果は薄いので、今度はアプリケーション側でキャッシュをさせる。 O/R Mapper には DBIx::Class を使っているので、そんな時は、 DBIx::Class::Cursor::Cached がお気軽で便利。 Cache オブジェクトには、Cache::Memcached::Fast を使用し、 schema を返す Mouse なオブジェクトのコードは以下のようになった。


 package SugokuII::API::DB;
use Mouse;
use Cache::Memcached::Fast;
use DBIx::Class::Cursor::Cached;
use SugokuII::Schema;

has 'connect_info' => (
    is      => 'rw',
    isa     => 'ArrayRef',
    default => sub {
        return [ 'dbi:mysql:dbname:localhost', 'user', 'pass' ];
    }
);

no Mouse;

sub connection {
    my $self   = shift;
    my $schema = SugokuII::Schema->connect( @{ $self->connect_info() },
        { cursor_class => 'DBIx::Class::Cursor::Cached' } );
    $schema->default_resultset_attributes(
        {
            cache_object => Cache::Memcached::Fast->new(
                { servers => [ { address => 'localhost:11211' } ], }
            ),
            cache_for => 60 * 60,
        }
    );
    return $schema;
}

__PACKAGE__->meta->make_immutable();
1;

これで、そこそこ負荷が下がったが、どうもまだ senna の全文検索周りが 遅い。そこでドキュメントを見てみると以下のような記述を発見。

Linux 2.6以降では、カーネルのバッファキャッシュを経由せずにファイルに非同期アクセスを行える AIO/DIOという機構が備わっています。 この機構を用いて、 VA Linux Systems Japan の北目さんがSennaのユーザレベルキャッシュ機能を実装しました。 低メモリ消費で高効率なキャッシュなので、メモリ資源の制約がシビアな環境で高い性能が要求される局面で効果が期待できます。

ということで手元の環境でも動作したので、環境変数を設定するため

# export SEN_AIO_ENABLED=1

してから mysqld を起動させてみた。 すると、上記した対策をあわせてかなーり mysql の負荷が減ったようだ。

あとは細かい、けどそこそこ重要な対策。主にトップページの見せ方を工夫してみた。 当初は「Hot Words」として最近検索された単語を頻度でソートして毎回動的に表示してたのだけど、 これがまた重たい。なので、徐々に数を減らしていったが最終的には表示しないように施した。 けれども、「全く表示させない」というのはベストの策ではないことにちょっとして気がついた。 というのも、検索窓だけあって他にたどるリンクがない場合、 ユーザーはおそらく適当な単語を最初に入力して検索を行うであろう。 すると、上記したキャッシュのヒット率が格段に悪くなるわけで、 対策の意味が薄れてしまうのだ。 なので、静的に全く固定でトップページに一つだけ

例: 柚木ティナ

と検索結果へのリンクを張っておいた。 これだと初めて訪れたユーザーもとりあえずはそこをクリックすることになり、 キャッシュにヒットするのでレスポンスは速くなる。 その分だけ全体的な負荷が下がるとみていいだろう。

ということで、以下が munin で出力したロードアベレージのグラフです。 所々途切れているのは、あせって munin のプロセス自体落としてたからですw 時間がピークを過ぎたとはいえ、そこそこ負荷が減っているのがわかると思います。

munin

以上、今回学んだことを含みまとめてみました。 後ほど別エントリーで書こうと思うけど、 サーバーの負荷についての対策や心構えについては この「キャパシティプランニング」という本が非常に刺激的なのでオススメです。

キャパシティプランニング ― リソースを最大限に活かすサイト分析・予測・配置
posted with yusukebe.com::AmazonSearch on 2009.7.7
  • John Allspaw
  • ペーパーバック / オライリージャパン
  • Amazon 売り上げランキング: 37076
  • Amazon おすすめ度の平均: 4.0
    • 4 ログをとるソフトの使い方と見方を書いています
Amazon.co.jpで詳細を見る

引き続き、「sugokuii beta」をよろしくお願いします。