41 ポイント 投稿者 xguru 2023-11-13 | 1件のコメント | WhatsAppで共有

教訓

  • よく知られた、実証済みの技術を使う
  • Keep it Simple
  • 過度に創造的に考えない(同一ノードを追加して拡張可能なアーキテクチャを選ぶ)
  • 選択肢を絞る
  • DBシャーディング > クラスタリング
  • 楽しく! (新任エンジニアでも初週からコードに貢献可能)

2010年3月: クローズドベータ、エンジニア1人

  • MySQL 1台 + Webサーバー(Django + Python)1台 + エンジニア1人(共同創業者2人を含む)。Rackspaceでホスティング

2011年1月: ユーザー1万人(MAU)、エンジニア2人

  • AWS EC2 Webサーバースタック(EC2 + S3 + CloudFront)
  • Django + Python
  • 冗長性のためのWebサーバー4台
  • NGINX をリバースプロキシ兼ロードバランサーとして使用
  • MySQL 1台にRead-onlyセカンダリ1台
  • Counter用MongoDB
  • 1つのタスクキューと2台のタスクプロセッサ(非同期処理)

2011年10月: 320万 MAU、エンジニア3人

  • 10か月間で急成長し、1.5か月ごとにユーザー数が2倍に増加
  • 2011年3月のiPhoneアプリ公開が成長を牽引した要因の1つ
  • 急成長に伴い、技術面の問題がより頻繁に発生
  • Pinterestはこの時にミスをした: "アーキテクチャを過度に複雑にしてしまった"
  • エンジニアは3人しかいないのに、データに使うDB技術は5種類あった
  • MySQLを手動でシャーディングしながら、同時にCassandraとMembase(現在のCouchbase)でデータをクラスタリングしていた
  • 彼らの「複雑すぎるスタック」
    • Webサーバースタック(EC2 + S3 + Cloudnfront)
      • Flask(Python)へバックエンドの移行を開始
    • Webサーバー16台
    • APIエンジン2台
    • NGINXプロキシ2台
    • 手動でシャーディングされたMySQL DB 5台 + 読み取り専用セカンダリ9台
    • Cassandraノード4台
    • Membaseノード15台(3つの独立クラスター)
    • Memcacheノード8台
    • Redisノード10台
    • タスクルーター3台 + タスクプロセッサ4台
    • Elastic Searchノード4台
    • Mongoクラスター3台
  • クラスタリングはうまくいかなかった
    • 理論上は、クラスタリングはデータストアを自動的に拡張し、高可用性とロードバランシングを実現しながらSPOFをなくしてくれるが
    • 残念ながら実際には、クラスタリングは複雑すぎて、アップグレードの仕組みが難しく、大きなSPOFを抱えていた
    • 各DBには、DBからDBへルーティングするクラスター管理アルゴリズムがある
      • DBに問題が発生すると、新しいDBを追加してそれを管理しなければならないが
      • Pinterestのクラスター管理アルゴリズムにバグが発生し、全ノードのデータが破損し、データのリバランシングが停止し、いくつかの修復不能な問題が起きた
  • Pinterestの解決策は?
    • システムからすべてのクラスタリング技術(Cassandra、Membase)を削除
    • (より実証済みの)MySQL + Memcachedに全面移行

2012年1月: 1100万 MAU、エンジニア6人

  • 約1200万から2100 DAU
  • この時点でアーキテクチャの単純化に時間を割いた
  • クラスタリングとCassandraを除去し、MySQL、Memcache、シャーディングに置き換えた
  • 単純化されたスタック
    • Amazon EC2 + S3 + Akamai(CloudFrontの代替)
    • AWS ELB(Elastic Load Balancing)
    • 90 Web Engines + 50 API Engines(Flask使用)
    • 66 MySQL DBs + 66 secondaries
    • 59 Redis Instances
    • 51 Memcache Instances
    • 1 Redis Task Manager + 25 Task Processors
    • シャーディングされたApache Solr(Elasticsearchの代替)
    • 削除したもの: Cassandra、Membase、Elasticsearch、MongoDB、NGINX

PinterestがDBを手動シャーディングした方法

データベースシャーディングは、単一のデータセットを複数のデータベースに分割する方法
利点: 高可用性、ロードバランシング、データ配置のためのシンプルなアルゴリズム、データベースを容易に分割して容量を追加できること、データを見つけやすいこと

  • 最初にシャーディングしたときに問題があったため、数か月かけて段階的に手動シャーディングを進めた
  • 移行手順
    1. 1 DB + Foreign Keys + Joins
    2. 1 DB + Denormalized + Cache
    3. 1 DB + Read Slaves + Cache
    4. 複数台の機能別にシャーディングされたDB + Read Slaves + Cache
    5. IDでシャーディングされたDB + Backup Slaves + Cache
  • データベース層でテーブル結合と複雑なクエリを排除し、多くのキャッシュを追加
  • データベース全体で一意制約を維持するために多大な労力が必要だったため、ユーザー名やメールアドレスのようなデータは巨大な非シャーディングDBに保存
  • すべてのテーブルがシャードに載る

2012年10月: 2200万 MAU、エンジニア40人

  • アーキテクチャはそのまま維持しつつ、同じシステムを数台追加
    • Amazon EC2 + S3 + CDNs(EdgeCast, Akamai, Level 3)
    • 180 web servers + 240 API engines(Flask)
    • 88 MySQL DBs + 88 secondaries each
    • 110 Redis instances
    • 200 Memcache instances
    • 4 Redis Task Managers + 80 Task Processors
    • Sharded Apache Solr
  • ハードディスクからSSDへの移行を開始
  • 重要な教訓: 限定的で実証済みの選択肢(limited, proven choices)が良かったということ
  • EC2とS3にこだわったことで構成の選択肢が制限され、悩みの種が減って単純性が高まった
  • しかし新しいインスタンスは数秒で用意できるようになった。つまり、わずか数分で10個のMemcacheインスタンスを追加可能

Pinterestのデータベース構造

  • IDs
    • Instagramと似ており、シャーディングのためにユニークなID構造を持つ
    • 64bit IDの構成
      • Shard ID : どのシャードか。16 bit
      • Type : オブジェクトタイプ(Pinのようなもの)10 bit
      • Local ID : テーブル内の位置。38 bit
    • このIDのLookup構造は、単純なPythonの辞書にすぎない
  • Tables
    • オブジェクトテーブルとマッピングテーブルがあった
    • オブジェクトテーブルは、Pin、Board、コメント、ユーザーなどのためのもの。ローカルIDがMySQL Blob(JSON)にマッピングされる
    • マッピングテーブルは、Boardをユーザーに対応付けたり、いいねをPinに対応付けたりするなど、オブジェクト間のリレーショナルデータのためのテーブル。完全なIDとタイムスタンプにマッピングされた完全なID
    • すべてのクエリは効率のためにPK(主キー)またはインデックス参照を使う。すべての結合を排除

1件のコメント

 
xguru 2023-11-13

Instagramがわずか3人のエンジニアで1400万人のユーザーを獲得した方法
これと同じシリーズの文章で、内容もつながっています。
「シンプルに保つこと。よく知られ、実証された技術を使うこと」