狠狠撸

狠狠撸Share a Scribd company logo
こんな僕でも
一億枚さばけた
30days albumインフラ成長の歴史
2012.4.19 MySQL Casual Talk #3
Ryo Kuroda
@lamanotrama
自己紹介
● 株式会社 paperboy&co.
● インフラエンジニア
今日は30days Albumの話
サービス紹介
● http://30d.jp
● 2008年4月 ~
● 写真共有?保存サービス
○ 期間限定(30日)オンラインアルバム
○ 合言葉で共有(閲覧、投稿)
● 2009年12月 ~
● 容量無制限オンラインフォトストレージ
登録枚数
● 最近累計登録枚数が1億枚を超えました
● 2012.4.19現在 108,491,796枚
● 容量 202TByte
何が「こんな僕でも」なのか
前職
● ホスティング会社サバ管
● 台数はそこそこ
● 2000台位かな
● 皆さん等しくそれなりに使えればOKな世界
なにそれ?
● パフォーマンスチューニング?
● HA?
● スケーラビリティ?
(*別のスキルは必要です)
そんな自分が
2年半前に入社していきなり30days Albumのイン
フラメイン担当に。
色々あったけど、サービス、インフラと共に成長さ
せて頂き、1億枚を捌けるようになりました。
最初にごめんなさい
MySQLの話が少ないです。。。
割とセオリー通りの運用しかしてないので、エクス
トリームな話を期待されるとちょっとあれです。
本题开始
まず当时の构成
2008~2009年頃の構成 全体概要
リバース
プロキシ
(Perlbal)
リバース
プロキシ
(Perlbal)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
(Mogilefs)
ストレージ
(Mogilefs)
Webアプリ
(lighttpd
+
Rails)
Webアプリ
(lighttpd
+
Rails)
非同期
ジョブAPI
(lighttpd
Catalyst)
非同期
ジョブAPI
(lighttpd
Catalyst)
ジョブ
サーバー
(Gearman
TheSchwar
tz)
ジョブ
サーバー
(Gearman
TheSchwalt
z)
データベー
ス
(MySQL)
データベー
ス
(MySQL)
画像周りの仕組み
Perlbal
ストレージAPI
トラッカー
(mogilefsd)
トラッカーDB
(MySQL)
ストレージ
ノード
(mogstored)
MySQLをつかってるところ
リバース
プロキシ
(Perlbal)
リバース
プロキシ
(Perlbal)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
(Mogilefs)
ストレージ
(Mogilefs)
Webアプリ
(lighttpd
+
Rails)
Webアプリ
(lighttpd
+
Rails)
非同期
ジョブAPI
(lighttpd
Catalyst)
非同期
ジョブAPI
(lighttpd
Catalyst)
ジョブ
サーバー
(Gearman
TheSchwar
tz)
ジョブ
サーバー
(Gearman
TheSchwalt
z)
データベー
ス
(MySQL)
データベー
ス
(MySQL)
1. days
2. storage_api
3. mogilefs
1. days
アプリケーション用
● 写真、アルバムの論理データ
● 誰々さんの、どのアルバムの…
● 保存期限
● カメラの種類
● Exif
2. storage_api
storage_api用
● 全てのMogileFSオブジェクトへのAPI層
○ アプリケーション、JOBワーカとMogileFSへの橋渡し
○ HTTP GET/PUTで画像の出し入れ
● ファイルのメタデータを管理
○ content-type, content-length
● サービス種別を管理
○ 30days、logpi、puboo
3. mogilefs
MogileFS用
● オブジェクトの物理的な場所
○ device
○ host
● オブジェクトの複製、再配置の為のジョブキュー
他にもジョブサーバ(TheSchwartz)のジョ
ブキュー用や、顧客管理用DBがあります
が、今回は端折ります。
全て画像絡み
扱う枚数が増えればDBの負荷も上がる
● 管理枚数
● 閲覧数
● アップロードペース
より詳しくは
アーキテクチャの詳細は過去のスライドをご覧下さ
い。
● 関西オープン2008
http://www.slideshare.net/mizzy/2008-30days-album-
presentation
● YAPC::Asia Tokyo 2010
http://www.slideshare.net/kyanny/inside-30days-
albumlaterstory-5452817
今日あまり触れないDB周り以外の苦労話も入って
ます。
2008年 ~ 2009年
安定期
平和な時代
とにかく平和。dbサーバのメモリを2GBから4GBに
増やしたくらい。
やること無い。このサービス楽だわー。
(実はなにをやるべきか知らないだけ。)
2010年 春 夏
兆候
だんだんもっさりしてきた
とりあえず各種コンポーネントを追加。
● storageノードに別のroleを組み合わせ
○ storage_api
○ job worker
storage006.30d.jp
storage003.30d.jp
storage002.30d.jp
今まで1ホスト1 role (puppetのマニフェスト上) だったのを
storage001.30d.jp
ストレージ
(Mogilefs)
……
storage003.30d.jp
storage002.30d.jp
storage006.30d.jp
storage005.30d.jp
storage004.30d.jp
1ホストに複数roleを割り当てて余剰リソースを活用
非同期
ジョブAPI
(lighttpd
Catalyst)
ジョブ
サーバー
(Gearman
TheSchwar
tz)
ストレージ
(Mogilefs)
ストレージ
API
(lighttpd
Catalyst)
storage001.30d.jp
ストレージ
(Mogilefs)
ストレージ
API
(lighttpd
Catalyst)
DBおもくね?
● いよいよDBがボテルネックになってきたぽい
● 付け焼刃の対応でヘタうつ
とりあえずチューニングで乗り越えようとして
OOM起こしたり。
とはいうものの、この辺でようやくパラメータチュー
ニングのセオリー等をある程度体で学び始める。
やるべきとこも見えてきた。
days dbにindexを追加
● Maatkitマジ便利(って刺身さんがいってた)
○ mk-query-profiler
○ mk-query-digest
○ 刺身さんのYAPC資料
● アルバム、ライブラリの表示レスポンスはある程
度改善
● アップロードや画像変換の処理遅延は引き続き
悪化
この辺でアップロードペース(容量増加ペース)がグ
ストレージ容量グラフ
● 週末には 500GB/日
○ 2009年段階では多くて200GB
● 枚数にして 10万枚/日
● 容量追加が間に合わない
● 空間効率が悪い
● ベンダー製はコストが…
自作サーバー登场
MP100
● 高集積
○ 2U
○ 2TB * 7
● 低コスト
○ ひみつ
● H/W好きで詳しい人がいた
○ マサキパワー100(kg)
入れ物のめどはたったが…
● jobの処理は相変わらず詰まる
● 特に夜間のピークタイムがきつい
● 写真をアップロードしても表示までに時間がか
かる
● 画像を回転しても返事がない
● まとめてダウンロード用のアーカイブファイル作
成がいつまで経っても終わらない
● よくよくDB観察するとstorage_apiがテーブル
ロックしまくってる
● 実はMyISAMだった
○ 実はあまり気にしたこともなかった
これによって
● jobワーカがサーバ性能通りの働きを発揮出来
ない
● 参照クエリもレスポンスが悪化し閲覧にも影響
この部分ね
リバース
プロキシ
(Perlbal)
リバース
プロキシ
(Perlbal)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
(Mogilefs)
ストレージ
(Mogilefs)
Webアプリ
(lighttpd
+
Rails)
Webアプリ
(lighttpd
+
Rails)
非同期
ジョブAPI
(lighttpd
Catalyst)
非同期
ジョブAPI
(lighttpd
Catalyst)
ジョブ
サーバー
(Gearman
TheSchwar
tz)
ジョブ
サーバー
(Gearman
TheSchwalt
z)
データベー
ス
(MySQL)
データベー
ス
(MySQL)
2. storage_api
2010年 秋
メンテナンス大会
サーバ追加してDBを分離
サーバを追加して、アプリケーション用と、その他
のstorage用のDBを分離。
● 新サーバにはSSDを採用
● 当然storage_apiはinnodb化
● ついでにdays、mogilefsはinnodb file per
table化
Before
mysql1.30d.jp
(master)
mysql2.30d.jp
(slave)
days
storage_api
mogilefs
job_queue
days
storage_api
mogilefs
job_queue
InnoDB MyISAM
After
mysql1.30d.jp
(master) mysql2.30d.jp
(slave)
days
db001.30d.jp
(master)
storage_api
mogilefs
job_queue
days
storage_api
mogilefs
job_queue
slaveの構成
諸事情により新サーバ用のslaveサーバを用意出
来なかったので、days DB用slaveサーバに相乗
り。
mysqld_multiは使わなかった
● なんだかんだで別々の方が扱いやすい
● わりとすぐに分離する予定だった
● puppetで構成管理するので都合が良かった
mysqld.second
initスクリプト、my.cnfを調整して2つのmysqldを起
動。
別のmy.cnfと、それを使うラッパースクリプトを作
成して運用。
● /etc/my.cnf.second
● /var/lib/mysql.second
● /etc/init.d/mysqld.second
● /usr/local/bin/mysql.second
● /usr/local/bin/mysqldump.second
puppet
30daysのシステムはわりと隅々までpuppetで構
成管理されています。
mysqlサーバのmanifest関して、もともと一台を扱
うようにしかデザインされていなかったので、作成
しなおしました。
base class
共通のリソース等
各データベース用class
各DBの固有情報
node定義
サーバのroleとして定義
puppetの話終わり
実際にはこれほど綺麗ではなく、こうしないとダメだ
な思うところも有るのですが、
重要なのは、システムのあるべき状態をバージョン
管理できて、開発者とも情報を共有出来るところに
あります。
極端な話、実際にサーバに適用するかどうかは別
としても導入する価値はあるともいます。
この後、
● days DBに更にindex追加
● appサーバ群もリプレースにより強化
● 内部ネットワークのギガ化
等も行い、過去最高の状態。
すごく早いよ!
~ 2011年 夏
2度目の安定期
2度目の安定期
少しずつ手を入れながら平和な日々が続く。
● 相乗りだったslaveも新サーバを追加して、別々
に
● railsの動作環境を Lighttpd+FastCGI から
Apache+Passenger に変更
○ パフォーマンスアップ、省リソース的にはあんまり効果無
し。安定はした。
● jobサーバ群をリプレースして強化
2011年 秋
days史上最大のピンチ
急に重くな(った気がす)る
● ぎりぎりアラート来ない程度の高負荷
● 昨年のテコ入れの効果を過信
更に…
予想を大幅に上回るアップロードペース
昨年同時期の数倍
● 週末の増量ペースが 1TB~2TB/日
● 枚数にして~28万枚
● 例の如くそのほとんどが夜間に集中
● 9月のシルバーウィークの影響もあるとは言え、
これは正直想定外だった
appサーバ、days DBがどちらもH/W性能の限界
(storage周りのDBは去年のSSD化で超余裕)。
ピーク時にアプリケーションサーバがまったく捌き
きれず、断続的にダウンする有様。
非同期
ジョブAPI
(lighttpd
Catalyst)
非同期
ジョブAPI
(lighttpd
Catalyst)
ストレージ
API
(lighttpd
Catalyst)
この部分がまじやばい
リバース
プロキシ
(Perlbal)
リバース
プロキシ
(Perlbal)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
(Mogilefs)
ストレージ
(Mogilefs)
ジョブ
サーバー
(Gearman
TheSchwar
tz)
ジョブ
サーバー
(Gearman
TheSchwalt
z)
データベー
ス
(MySQL)
データベー
ス
(MySQL)
1. days
Webアプリ
(Passenger
+
Rails)
Webアプリ
(Passenger
+
Rails)
さてどうする
● apache、passengerのチューニングでごまかし
ごまかし
● staticファイルのサーブをnginxに変更
● days DBにindexを足すが、目立った効果はな
し
● サーバを発注したが、納品は数週間後
数週間はもたんよね。
YAPC::Asia フォトスポンサー
2週間後に開催されるYAPC::Asia 2011 のオフィ
シャルフォトスポンサーにご指名して頂いていた。
このままだと絶対にDisられる。というか申し
訳ない。
とりあえず見れないのはやばい。見るだけでもなん
とかしなくては。
EC2 を使おう!
アルバム閲覧を含む一部GETリクエストをEC2へ
流して、凌ぐのだ。それしかない。
システムのサブセットをEC2上にオリャっと構築。
EC2を使ったシステム構成 
DC
AWS
静的
コンテンツ
更新
参照のみ
リバース
プロキシ
(Perlbal)
ストレージ
API
(lighttpd
Catalyst)
静的
コンテンツ
サーバ
(nginx)
Webアプリ
(Passenger
+
Rails)
セッション
サーバ
(Kyoto
Tycoon)
セッション
サーバ
(Kyoto
Tycoon)
Webアプリ
(Passenger
+
Rails)
写真データ
データベー
ス
(MySQL)
マスター
データベー
ス
(MySQL)
子スレーブ
データベー
ス
(MySQL)
孫スレーブ
ELB
データベー
ス
(MySQL)
スレーブ
孫slaveが必要だった理由
● masterが限界なので子slaveを増やしたくない
● 子slaveなインスタンスがいくつか兼任してたの
で出来るだけ落としたくない
○ ldapサーバ
○ puppetサーバ
○ セッションストレージ(kyototycoon)
● だが、DBのスケールアップ(ダウン)は柔軟に行
いたい。
子slaveはxtrabackupで作成(1)
1. EC2インスタンスに別ディスク(EBS)をmountし
とく
mount -t ext3 /dev/sdf /tmp/mysql
2. DC側のslaveからxtrabackupで直接データ転
送
innobackupex --user root --password=xxxx 
--slave-info --stream=tar4ibd 
--defaults-file=/etc/my.cnf 
/tmp/mysql |
gzip -c |
子slaveはxtrabackupで作成(2)
1. EC2側のslaveで差分ログ当てる
innobackupex --apply-log 
--ibbackup=xtrabckup_51 /tmp/mysql
2. データ差し替え
mv /var/lib/mysql{,.bak}; mkdir /var/lib/mysql
umount /tmp/mysql; mount /dev/sdf/ /var/lib/mysql
chown -R mysql. /var/lib/mysql
3. mysqld 立ちあげてxtrabackup_slave_info の
内容で change master 実行
master > 子slave間はSSL(1)
1. CA証明書、証明書、秘密鍵を作成
2. master側で設置、設定
[mysqld]
ssl-ca = /var/lib/mysql/ca-cert.pem
ssl-cert = /var/lib/mysq/server-cert.pem
ssl-key = /var/lib/mysql/server-key.pm
master > 子slave間はSSL(2)
1. slave側にも同様に証明書を設置
2. ssl有効化
CHANGE MASTER TO
MASTER_SSL = 1
MASTER_SSL_CA = '/var/lib/mysql/server-cert.pem';
3. 実際にやりとりを確認
tcpdump -nxX -s 1000 port 3306
孫slaveはEBSスナップショットで(1)
slaveのdata_dirは別disk(EBS)なので、スナップ
ショットから簡単につくれた。
1. slaveで
○ stop slave io_thread
○ mysqld stop
○ my.cnf に log_slave_update 追記
2. EBSスナップショット作成
3. スナップショットからEBSを複製
4. slave で
○ mysqld start
孫slaveはEBSスナップショットで(2)
孫slaveで
1. 複製したEBSをmount
2. mysqld start
3. stop slave; reset slave
4. change master
5. slave start
楽だ。
セッションストレージ
MemcachedからKyoto Tycoonに変更
● dual master
● memagentを使ってactive、backup構成に
○ DCのクライアント(rails、perlbal)は
■ DC上のをactive、
■ EC2上のをbackupとして指定
○ EC2のクライアントはその逆
● データは暗号化
DCとEC2のセッション共有(with memagent)
app001 app002 app201
DC AWS
ここ
Perlbal Perlbal
Rails
mem
agent
KT
Rails Rails
KT
mem
agent
mem
agent
memagentが一週間に一度なぜか落ちるので、後
にこの構成は止めました。
レイテンシも転送量も実は気にする程ではなかっ
たので、実質問題はなかったです。
haproxyを使ってリベンジしようと思ってますが、
rubyのmemcache-clientの仕様がネックで難航
中。
危機を乗り越えた
● とりあえず閲覧に関しては安定
● アプロードもDC側で専念出来るのでマシに
● 知る限りでは顿颈蝉りもなし
サーバが納品される
その後、待ちにまったサーバが納品され、
先ずはAppサーバを増強。
これが大きな間違い。
● appがリクエスト受けまくるがDB反応なし
● appサチる
急いで、DBサーバもリプレースしました…
平和がもどった
システム安定後、ゆっくりと
● mysql5.1から5.5にバーションアップ
● ファイルフォーマットをbarracudaに変更
● フロントのプロキシをperlbalからnginxに変更
○ perlbalが無くなったわけではなくnginxからperlbalとrails
に振り分ける形
○ perlbalは画像に対する認証も行なっているので簡単に
は置き換えできない
等を行って更に安定し、めでたく一億枚を超えまし
た。 めでたしめでたし。
2008~2009年頃の構成 全体概要
リバース
プロキシ
(Perlbal)
リバース
プロキシ
(Perlbal)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
(Mogilefs)
ストレージ
(Mogilefs)
Webアプリ
(lighttpd
+
Rails)
Webアプリ
(lighttpd
+
Rails)
非同期
ジョブAPI
(lighttpd
Catalyst)
非同期
ジョブAPI
(lighttpd
Catalyst)
ジョブ
サーバー
(Gearman
TheSchwar
tz)
ジョブ
サーバー
(Gearman
TheSchwalt
z)
データベー
ス
(MySQL)
データベー
ス
(MySQL)
2012年現在の構成 全体概要
リバース
プロキシ
(Perlbal)
リバース
プロキシ
(Perlbal)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
API
(lighttpd
Catalyst)
ストレージ
(Mogilefs)
ストレージ
(Mogilefs)
Webアプリ
(Passenger
+
Rails)
Webアプリ
(Pasesnger
+
Rails)
非同期
ジョブAPI
(lighttpd
Catalyst)
非同期
ジョブAPI
(lighttpd
Catalyst)
ジョブ
サーバー
(Gearman
TheSchwart
z)
ジョブ
サーバー
(Gearman
TheSchwalt
z)
データベー
ス
(MySQL)
データベー
ス
(MySQL)
フロント
リバース
プロキシ
(Nginx)
フロント
リバース
プロキシ
(Nginx)
AWS
サブセット
まとめ
● 実は成長してないのかもしれない
● 忙しくてもパフォーマンス監視だけは忘れずに
● SSDマジ強い
● (特に)足場であるDBは早めの増強を
质问あるかな
ご静聴有難うござ
いました。

More Related Content

30days album / MySQL Casual Talk #3