大規模環境におけるMySQLシャディング:Kubernetes上でのVitess実践ガイド

Database tutorial - IT technology blog
Database tutorial - IT technology blog

単一インスタンスのMySQLで直面する壁

ある夜、フラッシュセールの最中にメインデータベースのCPU使用率が95%に達したことを覚えています。秒間3,000クエリを処理していましたが、かつては20ミリ秒と軽快だったレスポンスタイムが、4秒近くまで膨れ上がっていました。私たちは標準的な手順に従いました。インスタンスサイズをアップグレードし、バッファプールを調整し、リードレプリカを追加しました。しかし、垂直スケーリングは行き止まりです。最終的には、どれほど資金を投じても解決できないハードウェアの天井に突き当たります。

シャディング(大規模なデータセットを管理可能な小さな断片に分割するプロセス)は、通常、データベースエンジニアリングにおける「最終ボス」です。MySQLやPostgreSQLでの手作業によるシャディングに苦労してきた私にとって、それはしばしばアプリケーション層のロジックが絡み合った脆弱な混乱状態でした. Vitessはそれを変えます。これはMySQLの上層に位置するクラスタリングレイヤーとして機能し、シャディングの複雑さを吸収します。そのため、アプリケーションからは100個のノードを単一のデータベースのように扱うことができます。

なぜVitessなのか?

YouTubeは爆発的な成長に対応するためにVitessを開発しました。現在、Vitessは何十億行ものデータを含むデータベースを管理しています。VitessはMySQLプロトコルを流暢に話すプロキシレイヤーを提供します。コード側で特定のレコードがどのシャードにあるかを知る必要はありません。Vitessはコネクションプーリング、クエリルーティング、そしてアプリケーションをオフラインにすることなくシャード間でデータを移動させる「リシャアリング」を処理します。これは手作業と自動組み立てラインほどの違いがあります。

環境のセットアップ

今日のVitessデプロイの標準は、Kubernetes用のVitess Operatorです。このウォークスルーでは、K8sクラスター(ローカルテストならMinikubeで十分です)とhelmが必要です。開始前に、環境に少なくとも4 vCPUと8GB of RAMがあることを確認してください。Vitessは効率的ですが、初期のオーケストレーションにはある程度のオーバーヘッドが必要です。

まず、リポジトリを追加してオペレーターをデプロイします分析:

# VitessのHelmリポジトリを追加
helm repo add vitess https://vitess.io/helm
helm repo update

# Vitess Operatorをインストール
helm install vitess-operator vitess/vitess-operator

オペレーターはクラスターの「脳」として機能します。カスタムリソース定義(CRD)を監視し、MySQLインスタンスとVitessコンポーネントが健全で同期された状態に保たれるようにします。

最初のキースペースの設定

Vitessの世界では、スタンドアロンの「データベース」という概念を超えて、キースペース(Keyspace)について話します。キースペースは、複数のシャードに分割できる論理的なグルーピングです。まだシャディングを行っていない場合、キースペースは標準的なMySQLスキーマとまったく同じように動作します。

commerceという名前のキースペースを持つクラスターを定義してみましょう。水平分割を実演するために、2つのシャードから開始します。この設定をvttest.yamlとして保存してください:

apiVersion: vitess.io/v2
kind: VitessCluster
metadata:
  name: production-cluster
spec:
  cells:
    - name: zone1
      gateway:
        replicas: 1
  keyspaces:
    - name: commerce
      turndownPolicy: Immediate
      partitionings:
        - equal:
            parts: 2
            shardTemplate:
              tabletPools:
                - cell: zone1
                  type: replica
                  replicas: 2

設定をクラスターにデプロイします:

kubectl apply -f vttest.yaml

このコマンドにより、オペレーターは2つの独立したシャードを起動します。各シャードは、MySQLインスタンスと、基盤となるデータベースプロセスを管理するサイドカーであるVTTabletで構成されます。

アーキテクチャの分解

Podが初期化されている間に、主要な構成要素を見てみましょう。3つの主要なコンポーネントがあることに気づくでしょう:

  • VTGate: トラフィックコントローラーです。アプリケーションはここに接続します。SQLを解析し、正しいシャードにルーティングします。
  • VTTablet: ガーディアン(守護者)です。各MySQLインスタンスの隣に1つのVTTabletが配置され、コネクションプールを管理し、データベースを「死のクエリ(queries of death)」から保護します。
  • Topology Service: 通常はetcdによって支えられており、すべてのシャードとタブレットがどこに存在するかを示す信頼できる情報源(Source of Truth)です。

VSchemaの力

Vitessはどのユーザーをどのシャードに割り当てるかをどのように判断するのでしょうか?このロジックはVSchema内にあります。VSchemaがなければ、Vitessは単なるプロキシにすぎません。これがあることで、シャディングエンジンとなります。

usersテーブルがある場合、「Vindex」(Vitess Index)を使用して行をシャードにマッピングします。以下は、ハッシュベースの分散を使用した実用的なVSchemaのスニペットです:

{
  "sharded": true,
  "vindexes": {
    "hash_vindex": {
      "type": "hash"
    }
  },
  "tables": {
    "users": {
      "column_vindexes": [
        {
          "column": "user_id",
          "name": "hash_vindex"
        }
      ]
    }
  }
}

ほとんどのマルチテナント・ワークロードにはhash vindexをお勧めします。データを均等に分散し、特定のサーバーがトラフィックの90%を処理して他のサーバーがアイドル状態になるような「ホットスポット」を防ぎます。

検証とアプリケーションの統合

PodがRunningステータスになったら、接続の準備は完了です。VTGateは標準的なMySQLサーバーと同一に見えるポートを公開します。既存のORMやデータベースクライアントは違いを認識しません。

ゲートウェイをローカル環境にポートフォワードします:

kubectl port-forward svc/production-cluster-zone1-vtgate 3306:3306

次に、標準的なクライアントを使用して接続します:

mysql -h 127.0.0.1 -P 3306 -u user commerce

ここでのエンジニアリング上の利点は「透過性(invisibility)」です。SELECT * FROM usersを実行すると、Vitessが両方のシャードにクエリを投げ、結果をマージして、単一のセットとして返します。開発者は複雑なデータルーティングロジックを書く代わりに、機能開発に集中できます。

モニタリングと高可用性

本番環境で状況を把握せずに運用(フライング・ブラインド)することは、災難への入り口です。Vitessには、クラスターの健全性を可視化するvtctldというウェブダッシュボードが含まれています。

# vtctldダッシュボードにアクセス
kubectl port-forward svc/production-cluster-zone1-vtctld 15000:15000

http://localhost:15000にアクセスして、レプリカを監視します。プライマリノードに障害が発生した場合、Vitess Operatorは自動的にレプリカをプライマリに昇格させます。私は実際にノード障害が発生した際に、アプリケーションの書き込み中断が10秒未満で済み、読み取りのダウンタイムがゼロだったのを目の当たりにしました。

深いオブザーバビリティ(観測性)を得るために、私は常に/metricsエンドポイントをPrometheusにスクレイピングしています。vttablet_query_countvttablet_query_error_countなどのメトリクスを追跡することで、パフォーマンスの低下がユーザーに影響を与える前に察知できます。

最後に

Vitessの導入は戦略的な転換です。新しいアーキテクチャコンポーネントが導入されますが、データ成長に対する厳しい制限が取り払われます。2TBのストレージ制限や秒間5,000クエリのボトルネックを恐れる必要がなくなれば、自信を持ってシステムを構築できます。水平スケーリングは、YAMLファイルを更新し、オペレーターに重労働を任せるのと同じくらい簡単になります。

Share: