mixiの年末年始対策2012-2013
はじめまして、運用部アプリ運用グループのainoyaと申します。 今年4月に新卒で入社して以来、はじめてエンジニアブログを書きます。
この記事は、デスクトップ版も大変使いやすいFedoraから書いています。
はじめに ~ mixi vs 正月 ~
mixiを支えるバックエンドには、mixiを影で支えるエンジニアによって 大量のアクセスをさばききる頑丈なシステムが構築されていました。 ですが、年末年始にはその頑丈なシステムを打ち破るほど想定外な負荷が押し寄せてきます。
それは、月間利用者1,400万人以上のユーザの方々が、mixi上で交わす年末年始の挨拶です。
mixi vs 正月 ~ 戦いの歴史 ~
これまで、mixiのエンジニアによって行われてきた正月の負荷急増対策は、毎年毎年必ず乗り越えなければならない 戦いとして、脈々と受け継がれてきた歴史です。 それでは簡単になってしまいますが、今までの歴史について、 mixiエンジニアブログのエントリを振り返りつつ各年の解説を試みたいと思います。 mixiエンジニアブログでその年の正月の負荷急増対策を書く。これも負荷対策に加えて毎年欠かさず行なっている恒例行事。 もはやあけおめエントリは、mixiエンジニアブログにおける古典芸能の様相を呈しております。この恒例、今後とも大事に育てていきたいものでございます。
【2008年1月1日】inoueさん
エンジニアブログで見つけられる、初代あけおめ対策の記事です。 あけおめの大規模負荷対策にそなえて、DBのストレージエンジンのベンチを取ってみると、 採番テーブルの用途ではInnoDBよりMyISAMのほうが良いという結果を得ています。 こちらは、2年後のkzysさんの記事にもつながる話です。
【2009年1月1日】kazeburoさん
kazeburoさんは年末年始の負荷増加を、あけおめことよろアタックと名付けました。 この年は、日記への大きな負荷が予想される年でした。
Q4Mを用いたDB遅延書き込みによる非同期処理システムによる負荷対策が導入されました。
【2010年1月1日】kzysさん
この年は、連番管理のためのDBをInnoDBではなくMyISAMで持つことで、DBのパフォーマンスを向上 させる対策について書かれています。
【2011年1月1日】koikeさん
gihyo.jp:2011年「あけおめアクセス」の対策と結果
この年は、あけおめことよろアタックのメインターゲットが、日記からボイスへシフトした年でもありました。
長きに渡る歴史、あけおめ対策記事執筆役は今年で何代目の襲名になるのか定かではないですが、 今年は私が新卒としての勉強も兼ね、色々調べてまいりましたので、あけおめ対策の解説を務めさせていただきます。
mixiエンジニアブログは今年もあけおめネタやめへんで!!
去年の戦いを振り返る
さて今回は、今年の正月、2012年1月1日に発生した大規模障害とその裏側についての話から スタートします。今年、2012年の1月1日は、すこしの間、mixiのレスポンスが悪化した状態になっていました。 そのとき、mixiの裏側では何が起こっていたのでしょうか?
mixiが止まったわけ
SocialStreamへの過負荷
SocialStreamとは、弊社の造語で、mixiにログインしたときに最初に目に入るであろう、下の枠線の部分のことです。 友人のあらゆる活動がフィードのストリームとして表示される”タイムライン”です。
(今回は、私の技術的理解が浅いため簡単なバックエンドの説明だけしかできませんが、 ほんとうは、SocialStreamにはわざわざ弊社だけのとくべつな造語で呼ばれるだけの理由があります。 いろいろな実装が詰め込まれた技術的にも面白いサービスなので、今後の解説記事にご期待ください。)
そんなSocialStreamの裏側では、DB(MySQL)に対してユーザの行動履歴データが大量に読み書きされます。 この大量のリクエストをさばききるため、SocialStreamでもmixiボイス等と同様、memcachedによるキャッシュ、Q4Mによる 遅延書き込みの仕組みやDBのユーザパーティショニング……代々に渡るあけおめことよろアタックとの戦いを踏まえ、 万全の負荷対策を講じていたはずでした。
しかし、あけおめことよろアタックの威力は想像の上をいくものでした。 2012年1月1日、0時0分を過ぎた頃、だんだんとホーム画面が重くなっていきました。そしてとうとう、SocialStreamが一部表示されない、などの問題が発生してしまいました。
Q4M
当時の記録を振り返ってみると、SocialStreamのDBへの書き込みの前段にあるQ4Mにジョブが数十万に溜まっていたそうです。 ところが、本丸のSocialStreamDB自体が詰まっているわけではない。 どうやら原因はここにありそうです。Q4Mのジョブを溜めるDBが何かのきっかけで詰まってしまったため、SocialStreamの機能に支障が出てしまったようです。
DB本体への書き込みを緩やかにする目的で導入したQ4Mですが、そのDBが詰まってしまったわけです。
2013年1月1日を乗り越えるために……
導入されて初めての正月を無事乗り切ることができなかったSocialStream。次こそは、生身で正月を乗り越えたい。SocialStreamが落ちたことについて、様々な原因を考え、以下のような対策を講じることにしました。
技術的対策
Q4M周りの対策
まず、問題の主な原因と思われるQ4M周りの構成について、次の準備をしました。
アプリケーションレイヤでの見直し
これはQ4MにとどまらずmixiのDB全体での話にもなってしまうのですが、Q4Mにジョブが詰まってしまう原因の一つとして、次のような仮説が立てられました。それは、今回のあけおめことよろアタックで起こるような大規模な負荷をトリガに、ユーザとグローバルのreverse proxyの通信経路のどこかでTCPセッションのクローズが正常に行われなかった場合、この接続断をアプリケーションが検出できず、TCPセッションに紐づいていたDBのコネクションプールが残り続けてしまうのではないかという問題です。 このようにして閉じられるべきタイミングで閉じられなかったDBのコネクションプールが滞留し続けると、MySQLはいずれToo many connectionを吐いてそれ以上接続を受け付けなくなり、DBが詰まる現象が発生します。
今回の仮説をもとに、アプリケーションレイヤでは、アプリとDBとのコネクションの切断を、より細かなタイミングで行うようコードに修正を加える対策をしました。これにより、上記の仮説で発生するDBの詰まりが起こる懸念を解消しました。
Q4Mの台数を増やし、workerの総数を減らす
次に、Q4M自体の設定調整です。Q4Mサーバの台数を増やすことで、Q4Mにジョブが詰まることのリスクを減らしました。 一方でジョブをさばくworkerの総数を絞ることで、DB本体への書き込み速度も緩めています。 このQ4Mサーバの数やworkerの数に関しては、DBへの書き込み速度との兼ね合いを見ながら最適なパラメータを見極めるべく、 今後もさらなるチューニングが必要なパラメータだと考えられます。
SocialStream以外のサービスへの負荷対策
APIサーバ負荷増加の見込み
一昨年が、日記からボイスへ負荷の集中がシフトしたように、今年もSocialStreamに負荷が集中するだけ、とは限りません。 例を挙げると、スマホの普及が進んでいる昨今、mixiではAPIサーバに対する負荷がじわじわと強まっております。スマホ端末のアプリからの アクセスだけではなく、mixiゲームからの利用も多いAPIサーバも、mixiにおいて決して落としてはならないもののひとつです。 APIサーバはSSL暗号化を担うproxyサーバとmod_perlサーバで構成されていますが、正月の時期に合わせてサーバ台数を増やして対応します。
サービスの一部を止める”縮退運転モード”
上記のような仕組みをもってしても耐え切れなかった場合に、それがmixiのサービス全体に影響が波及し、サービス全体のレスポンスが悪化するなどの状態に陥ることは避けたいです。そのために今年は、問題の生じたサービスを順次縮退できるような仕組みを用意しました。これにより、レスポンスの悪化してしまったサービスを一時的に縮退することで、サービス全体が落ちてしまう状態を回避します。
最後に
ユーザーファーストを宣言している弊社ですが、運用部はサービスを落とさない事でユーザーファーストに貢献しています。 今年は落とさない仕組みを用意し万全の体制であけおめ対策に望んでおりますので、皆様安心してアクセスしていただければと思います。
それでは年末年始にお会いしましょう!