BeanstalkやECSと戦っているSREチームの菅原です。P5をやりたいのにPS3もPS4も持っていないので指をくわえて羨ましがっている毎日です。この記事では、突然のアクセス増に備えるために、MySQLのスレーブを1〜2時間でスケールアウトできるようにした話を書きます。EC2を使っています。これは以下のような理由によるものです。AWS移行当時、RDSが無かった。MySQLを使ってダウンタイムゼロのマスタDBの切り替えを実現しています。RDSによるDNSベースの切り替えでは、どうしてもダウンタイムが発生してしまいます。主要DBは内外様々なサービスが利用しているため、レプリケーションの構成が複雑になっています。あるスレーブでは特定のテーブルをレプリケーションしていなかったり、またあるスレーブでは別のDBと同居していたりなど。RDSでこのような複雑な構成に対応することは難しいですスケールアウトと暖機TV放映など突発的なアクセス増があった場合、DBの負荷も増大するためスケールアウトが必要になることがあります。クックパッドの場合、サービスの特性としてリードのアクセスが圧倒的に多いため、DBをスケールアウトする場合には主にMySQLのスレーブを増やして、サービスに追加することになります。DBのデータはインスタンスにアタッチされているEBSのスナップショットとして、定期的にバックアップが取られています。新規にスレーブを作成する場合は以下のような手順になります。EC2のインスタンスを立てるスナップショットからEBSを復元してインスタンスにアタッチレプリケーションが追いつくのを待つこれで新しいスレーブができました。「早速サービスに入れよう」...とはいきません。作ったばかりのMySQLはデータがメモリにキャッシュされていないため、クエリが投げられるとディスクへの読み書きが発生し、処理に時間がかかってしまいます。スナップショットから復元されたEBSは、最初にブロックにアクセスしたときにはS3からデータをダウンロードしてくるため、その後のアクセスよりもレイテンシが増加します。このように暖機の行われていないスレーブをサービスに投入すると、サービスの応答速度の低下を招き、障害にもつながります。EBSの暖機gp2/1000GBのEBSをfioで暖機してみたところ、約19時間ほどかかりました。時間がかかりすぎるので「サービスに即時投入できるようにレプリケーションし続ける小さいインスタンスを用意しておく」とか「バックアップ用のスレーブのEBSを使って新しいスレーブを作る」などいくつか対策を考えてみたのですが、同じ部の先輩が「I2インスタンスを使うとよいのでは?」とアドバイスをくれました。I2インスタンスは大容量で高速なインスタンスストアが使えるインスタンスタイプです。DBで使っているファイルの総容量はEBSのサイズよりも小さいので、EBSからインスタンスストにコピーする方がEBS全体を暖機するより処理時間は速くなります。インスタンスストアはインスタンスに物理的にアタッチされるボリュームなので、暖機などしなくても高速に使えます。思って、総容量300〜400GBのDBのファイル群をcpを使って8並列でコピーしてみたところ、だいたい3時間ほどかかりました。EBSを暖機するよりはずっと短くなったのですが、それでもまだ時間がかかります。並列でcpを走らせるとある程度はスループットが出るのですが、ファイルごとの処理は直列なためサイズの大きいファイルがあるとそれに引きずられてスループットが下がってしまいます。そこで一つのファイルをチャンクに分けてddでコピーするツールを作り、それを使ってコピーしてみたところ、3時間かかっていた処理を1時間程度まで短縮することができました。MySQLの暖機MySQLのデータをメモリに乗せる作業は、以前はMySQL::WarmerをRubyにポートした自作ツールを作って、手作業で行っていました。サーバ上でメモリ使用量を見ながらウォームアップツールで主要なテーブルの暖機を行い、キャッシュが飽和したらサービスに少し入れてみて、スロークエリの出たテーブルをまた暖機...と悪い意味で職人的な作業であり、大量のMySQLに対して行うには非常に手間がかかりました。5.6のInnoDBバッファープールのプリロード機能を使って、暖機作業を高速化しました。InnoDBバッファープールのプリロード機能は、稼働しているMySQLのバッファプールの状態をファイルに出力しそれを起動時に読み込むことで、暖機の手間を省いてくれるものです。基本的には同じサーバ上のMySQLでの利用が想定されていると思うのですが、今回は稼働中のスレーブのバッファプールをダンプしてそれを新しく作ったスレーブに読み込ませることで、暖機作業を機械的に行えるようにしました。具体的には以下のような手順になります。稼働中のスレーブの1台で定期的にバッファプールのダンプを行うcronを設定するダンプファイルは圧縮してS3に保存しておく新規に作成したスレーブはS3から最新のダンプファイルをダウンロードして、起動時に読み込むディスク上のデータの物理的な配置が完全に一致しているかはやや疑問でもあるのですが、手作業よりも圧倒的に手間が少なく、また十分な効果も得られているのでこの方法をとっています。現在、MySQLのスケールアウトが必要な場合、以下のような手順で行っています。Kumogataを使ったCloudFormationのテンプレートを準備しておく環境変数でサーバ台数を指定できるようにしておき、CloudFormationで必要な台数のインスタンスを起動するCloudFormationによって、起動したインスタンスには最新のバックアップから作成されたEBSがアタッチされるインスタンスが起動するとcloud-initの起動時スクリプトによって以下の作業が行われるMySQLのセットアップEBSからインスタンスストアへのデータのコピーS3からバッファプールのダンプファイルをダウンロードMySQLが起動してレプリケーションの再開とバッファプールのロードを行うレプリケーションが追いついてバッファプールのロードが終わると、Slackに通知が来る新しいスレーブを人間がサービスに追加するまとめこの仕組みを導入することで、MySQLのスケールアウトのために「TV放映の前日、前々日から準備を始めて」「19時間ちかくを暖機に費やして」「職人芸でサービスに追加」していた作業が、「TV放映の当日、1〜2時間前にコマンドをたたいて」「Slackに通知が来るまで放置して」「通知来たらおもむろにサービスイン」といった具合に、大幅に省力化・短時間化できました。今後もそんな作業があればさっさと自動化して、QoLの向上を図っていきたいものです。使ったセキュリティログ検索基盤の構築こんにちは。コスト最適化についてご紹...2019-06-17レシピ検索を支えるレガシーでクリティカルな大規模バッチを刷新した話こんにちは、会員事業部の新井です。インタプリタを開発している笹田です。使ったセキュリティログ検索基盤の構築サービス特性にあった検索システムの設計戦略クックパッド採用説明会「クックパッドはサービスの作り手を採用したいんです。/*}*/スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。