Dropbox のスケールとか

Python なサービス みんな大好き Dropbox のスケールとかメモ。以下のページ辺りからピックアップ。Parted? みたいなので、続編がでたら追記するかも。

スケール関係ないですが、2006 年当時はオンラインストレージサービスがいっぱいあったようで、VC から資金調達したときのやり取りがおもしろい

  • VC "クラウドストレージサービスなんて腐るほどある"
  • Drew "なにか使ってるのありますか?"
  • VC "NO"
  • Drew "..."

完璧で、スケーラブルで、クロスプラットフォームなクラウドストレージ!当時、プライベートベータのビデオが 12000 digg (<- 懐かしい) され、ベータリストの登録が 1 日で 5 千人から 7 万人に増えたことも。現在5000 万人のユーザが、2 億 5 千万デバイスから、48 時間で 10 億ファイル保存してるとのこと。ファイルの POST/PUT で 5787 rps となると GET を合わせると。。。すごいですね!

スケールの記事を書かれているのは、2011 年まで Dropbox でスケールを担当されていた Rajiv Eranki (← URL w) 氏です。Dropbox のバックエンドはほとんど 1 ~ 3 人で面倒を見ていたとのこと。順不同で以下抜粋。なお、Dropbox さんは有効であるのは間違いないですが、ストイックと思われる箇所もあるので、18 最未満の方は保護者の同意の下w

>>> 利用しているテクノロジー

  • 言語: ほとんど Python, ちょっとだけ C
  • データベース: MySQL
  • WSGI: Paster / WAF: Pylons / テンプレートエンジン: Cheetah
  • ファイルブロックの保存と提供: S3/EC2
  • キャッシュとか (セッションストアも?: memcached
  • フロントエンドサーバ: nginx
  • ロードバランサ: haproxy (nginx と、アプリケーションサーバの間)
  • 監視: ganglia, nagios, Pingdom
  • IP と位置情報のマッピング: GeoIP

これらの技術を選んだ基準は "信頼性" だそうです。

MySQL を選んだ理由は、当時 Postgres のレプリケーションがビルトインじゃなかったから。それとコミュニティがでかいし、問題があったとしても Google, Yahoo, Facebook が先にパッチ送ってくれる(w

ORM に SQLAlchemy を使っていたけど、ORM 嫌いだし対応がとても厄介だったらしい。結局 SQLAlchemy でローレベルで SQL を組み立てるよう変更したそうです (具体例の記載が無いので分からないですが恐らくこういうこと?)。

テクノロジーの選択に際するアドバイスは、"動作が軽量で、他の多くのサービスで利用されていること、もしくはプロジェクトのコントリビューターになりたいもの" を選ぶ。

>>> 余分に負荷をかける

よく利用するテクニックのひとつ。本番環境でわざと余分に負荷をかける。例えば memcached は必要以上にリードする。memcached が壊れたら、その重複させてるクエリーを止めて解決までの時間を稼ぐ。なぜ事前に計画を立てないか。監視で検出できないぐらい急な障害が何度も発生したから。また 限界を知る ことができるから。

>>> 各アプリケーション用の分析

数千台のサーバの数千の統計データを集計したグラフが便利。ほとんどのモニタリングソリューション (out of the box - 箱から出してすぐ使える、テンプレート的なやつ) は、この種の負荷は考慮されてない。memcached, cron, と ganglia で実現。グラフを見たい時に、スレッドローカルメモリバッファに保存できる。その統計を毎秒 memcached にタイムスタンプを付けて保存。毎分その集計結果を ganglia にポストして、memcached からクリア。これにより何千もの統計を調査できるようになった。

Here is one summary graph that we found the most useful:

縦軸が平均レスポンスタイム。横軸は時間。このグラフにより、レスポンスタイムが 1:00 ぐらいに急上昇していて、MySQL のコミットフェーズで何かが起きてるのが分かる。CPU は平均応答時間から他のすべてを差し引いたもの (関知していないやつ)。

グラフ上に、デプロイや AWS の停止期間などのイベントを表示するのも素敵

>>> bash による分析

シェルは素敵だよ!!

例えば Web サーバのデバッグ。なにかが急上昇していないかログから調査したい場合、

 Apr 8 2012 14:33:59 POST ...
 Apr 8 2012 14:34:00 GET ...
 Apr 8 2012 14:34:00 GET ...
 Apr 8 2012 14:34:01 POST ... 

こんなログだったら

cut -d' ' -f1-4 log.txt | xargs -L1 -I_ date +%s -d_ | uniq -c | (echo "plot '-' using 2:1 with lines"; cat) | gnuplot

こんなコマンドで、すぐに何が起きているかが把握できるグラフを取得できます。

お勧めなコマンドたち: sed, awk, grep, cut, head, tail, sort, uniq, tr, date, xarg

よく使う sed, awk コマンドのチートシートはブックマークしてる: sed , awk

追記: id:torazuka さんによる素敵な解説 -> "メモ: テキストログをgnuplotで表示するコマンドの例"

>>> ログスパムは超役に立つ

Web サーバのログ内にスパムなログを吐いていて、意図せず何度も助けられた。例えば、競合状態をデバッグするの時に "FUUUCCKKKKKasdjkfnff" が出力されてなかったことで、その問題が起こっている場所を特定できた。(微妙。。

冗長なログを削除するのは魅力的だけど、それで何度後悔したことか。

>>> 想定される障害を確認する

障害ポイントを把握して、そのフェイルオーバーさせる場合は、時々その動作をテストする。無作為にネットワークからサーバを切り離し、そのフェイルオーバを確認する (やった方がいいのでしょうけど、正直怖い。。

  • フェイルオーバー後に負荷があがることで、フェイルオーバープロセスによりカスケードされたことを把握できます (カスケードフェイルオーバー)
  • フェイルオーバー以降、コードの書き換えや、データベーススキーマの変更や、内部 DNS の変更等が想定されます。それ以降動作させてなかったスクリプトには、古い環境に依存しているかも知れません。

これは平常時に把握した方が良いので、故意に (cron でプロセスをリスタートし、memcached をクリアする等) 発生させるのがベストです。本番サイトでこんなテストをするのは馬鹿らしく思うかもしれませんが、テスト環境では十分ではありませんし、これは良い保険になります。

>>> めったに実行されないものを実行する

上記と同じように、めったに実行されないコードを実行する。毎月 cron で実行しているものを、毎日 dry-run させることにより、コミット後しばらく経ってデバッグする必要がなくなります。モジュールのインポート確認だけでも助けになります。手動で実行しているバッチ (ユーザ状態の変更や診断など) も同様。

>>> 均等に保つ

以前、ユーザデータを 2 つのシャードに保存していたけど、いっぱいになったので、シャードを 1 個追加した。それが失敗だった。2 つのシャードはほぼ同じペースで増えていったけど、追加したシャードはものすごい勢いで増えてしまった。なので再度リハッシュする羽目に。2 つのシャードをそれぞれ分割し、均等に保つ方が良い (トリッキーだけど)。

ハードウェアでも一緒。機種は少ない方が良い。コストがかかるかもしれないけど、価値がある。

>>> ダウンタイムログを保持する

サイトのダウンや性能低下の発生毎に、その開始時間と終了時間、原因 (コードレビューがまずかった。監視の不足。ログのオーバフローなど) を記録する。これにより、"ダウンタイムを最小限に抑えるために、最も効果的なのは何か" が分かる。

>>> UTC

すべて UTC にする!サーバタイム、データベースなど。いくつかのソフトウェアは UTC 以外を適切に取り扱わないので、絶対に使わない!Dropbox では壁時計まで UTC にしてる (へーへーwww

ユーザに時刻を表示するときだけ、タイムゾーンを変換する。

>>> 試す前に、シュミレーションと分析を

プロダクトとは違い、バックエンドをエンジニアリングする際の目標 (ページロード時間の最適化や稼働時間など) や効果を予測するのは難しい。何かが役に立つと思った際は、実装する前にそれをシミュレートする。例えばプロセッサーの高速化が役に立つと思った場合は、1 つのワーカーでそれを実行してみてその違いを見てみる。または、データベースサーバをレイテンシが高い場所に移動したいと思った場合は、ローレベルでレイテンシを追加してみて、何が起きるかを見てみる。または、データベース外に何かをキャッシュしようと思った場合は、影響をシミュレートし、ヒットを計算するなどなど

>>> セキュリティと利便性のトレードオフ

Dropbox に保存されているのは個人のファイルなので、セキュリティはとても大事。しかし、サービスが異なれば対応も異なりますし、たいていのセキュリティ判断はユーザーやプログラマーにとって不便となります。

例えば、ほとんどの Web サービスで、ユーザ名かパスワードのどちらかを間違えて入力した場合、間違えてるとは通知しますが、どちらを間違えているかまでは通知しません。これはユーザ名の推測に使えないためセキュアですが、どのユーザ名で登録したか覚えてない人にとっては不便です。ユーザ名を公開してもかまわない (公開フォーラムとか Pinterest みたいなサービス) と判断した場合は、ユーザに便がいいように情報の公開を検討する。

情報をやり取りしないサーバ間にファイアウォールを設けるとか。

うん。抄訳になってしまいました。おもしろかった!解釈間違ってたら教えていただけると喜びます。ストイックな箇所もありますが、それもあって安定したサービスを提供できてるんだと思います。色々と勉強になりました!I love dropbox :)

コメント

このブログの人気の投稿

Python から Win32 API 経由で印刷する

Disqus のスケール - Django 編

Django と Python 3 - #python_adv