データベース
GitLab は単一のデータストアに依存するシングルアプリケーションです(厳格な耐久性要件の文脈で使用する用語で、例えば Redis に対する PostgreSQL のことを指します)。
この指針が GitLab のプロダクト開発を方向付けています: GitLab は SaaS ファースト ではありますが、SaaS のみではありません。データベースの観点では、GitLab は一般的に論理データベースを使用して単一データベースクラスターを持つセルフマネージド構成をサポートしています。スケールが必要な場合にのみ、GitLab.com がそうであるように、単一クラスターを複数に分割することを検討します。これは、コードベースが安定した状態を保ち、スケーラビリティに対応するための柔軟なバックエンド戦略を活用できることを意味します。セルフマネージドと GitLab.com は引き続き単一アプリケーションとして動作し、セルフマネージドは特にスケールする柔軟性を提供しながらシンプルさを維持し続けます。
複数のデータストアに対する根本的な反対はありませんが、特に様々なデータエンジンが関わる場合にあまりにも多くなることの落とし穴を避けたいと考えています。追加のデータストアは管理と開発の複雑さをもたらします。新しいデータベースを使用したり既存のものを採用したりすることにはトレードオフが伴い、スケールで綿密に管理する必要があります。別のデータストアをデプロイする前にいくつかのゲートキーパーを設けており、以下のガイドラインは最善の行動方針を決定し、どのように進めるかを理解するためのものです。
これらのガイドラインは、Database Working Group の用語集に大きく依存しています。
新しいデータベースが必要だ
新しいデータベースが必要だという要求はより一般的になってきており、一見シンプルに見えますが、特に新しいサービスや新しいチームにとっては見かけによらず複雑です。
まず第一に、データベース(どのデータベースでも)へのアクセスは、本番環境と関連するアクセス制御および手順の範囲内でのみ可能です。新しいリソースを要求するフィーチャーとサービスは、本番準備レビューを受ける必要があります。
次に、特に保存・クエリするデータの種類、メインデータベースとの密結合度、スキーマと設定の管理方法に関して、その言葉が実際に何を意味するかを完全に理解する必要があります。
第三に、リソース使用率(スペース要件、トランザクションレート、両者の予想される成長)の観点からどのような意味を持つかを理解する必要があります。
最後に、データが新しいデータストアエンジンを必要とするかどうかを理解する必要があります。これは、デプロイメント自体、継続的なメンテナンス(アップグレードなど)、オブザーバビリティの統合、そして最も重要なインシデント時のトラブルシューティングの観点から、本番環境にデプロイされた際に大きな影響を持ちます。
私たちはリレーショナルデータベース(PostgreSQL)をプライマリメタデータストレージエンジンとして使用しています。さらに、GitLab の機能に不可欠ではあるもののより動的なデータを保存するデータ構造ストア(Redis)も使用しています。
リレーショナル: PostgreSQL
PostgreSQL は私たちが選択するリレーショナルデータベースエンジンであり、最近まで、プロジェクト、Issue、マージリクエスト、ユーザーなどのすべてのメタデータが単一クラスターに存在していました。そのスキーマは Rails アプリケーション(db/structure.sql)によって管理されています。このデータストアをメインデータベースと呼んでいます。スケーラビリティのニーズが高まるにつれて、それらに対処するためのベストプラクティスを採用しました。一部のアイテムはデータベースから抽出され(差分が最初のものでした)、一方で他のものは既に独立したサービスであり低いデータ結合要件を持っていたため(Registry と Praefect)、別の論理データベースまたはインスタンス(スケール時)にデプロイされました。また他のものはそのスケール(および密結合を回避する方法を見つけたため)のために分解されました(CI)。
データ構造: Redis
Redis は、キュー(Sidekiq ジョブは JSON ペイロードにマーシャルされます)、永続状態(セッションデータと排他リース)、キャッシュ(ブランチやタグ名などのリポジトリデータ、ビューパーシャル)などの特殊な非リレーショナルニーズに使用されます。Redis はアプリケーションの重要なコンポーネントですが、PostgreSQL と同じ耐久性制約で使用されているわけではありません。
考慮事項
適切なデータベースを決定するために、4つの基本的な質問に答える必要があります:
- アプリケーションを構成するコードベースの種類は何か?
- アプリケーションが保存する必要のあるデータの種類は何か?
- アプリケーションがデータベースに対して実行する必要があるクエリの種類は何か?
- 現在および近い将来において、消費されるスペース、トランザクションレート(読み取りと書き込み)、レイテンシの観点から予想されるリソース使用率はどの程度か?
最初の3つの質問への回答は事前に把握されている可能性が高いです。これらは本当にアプリケーションに組み込まれているからです。最後の質問はやや不明確になりがちで、正確な回答は必要ありませんが、大まかな見積もり(デプロイ時点と少し先の将来の両方)が必要です。Database、Scalability、Memory などの専門チームは、これらの未知の要素を明らかにするのに役立ちます。いずれにせよ、これらの質問への回答は特定の技術(いくつかの例外を除き)を避けるべきです。追加の入力として、ビジネス期待値と過去の成長に基づく GitLab.com のスケーリングモデルを参照して将来のスケーリング要件を理解することができます。
デフォルトの回答: メイン Postgres データベース
従来のデフォルトの回答はメインデータベース(PostgreSQL)を使用することでした。しかし、主に3つの理由から、もはやそれが当てはまらない段階に来ていると思われます:
- 可用性を確保するために、特にトランザクションレート、接続、メモリ使用率の観点から、GitLab.com のメインデータベースへの負荷を慎重に管理する必要があります。
- プロダクトエコシステムは既存のテクノロジースタックの統合を通じて多様な形で進化しており、より特殊化されたデータニーズに直面しています。
- GitLab.com のメイン Postgres データベースは OLTP(Online Transaction Processing)のみを対象としています。特にスケール時に、OLAP(Online Analytical Processing)はデータベースに著しい劣化をもたらし、特にクラスターレプリケーションに影響します。
一般的に、コードベースがメイン RoR アプリケーションの一部であれば、スキーマが RoR によって管理されており、コードが Rails コードベースとかなり密接に結合している可能性が高いため、おそらくすでにメイン PostgreSQL データベースを使用しています。ただし、新しいエンティティは慎重に管理する必要があります。可用性を確保するためにキャパシティプランニングの懸念事項に対処しなければならないためです。Development の Database Group とインフラチームは、Redis にも同様に適用されるこの点で最良の情報源です。
例外
スケーラビリティの懸念から、現在、CI テーブルを別のクラスターに移動することで、メインデータベースの最初の機能分解を実施しています。CI 関連のコードベースはメイン RoR アプリケーションの一部ですが、CI テーブルはメインデータベースの全体サイズの約40%と書き込みの約50%を占めています。データベースの残りの部分との密結合は比較的緩いため、最小限の変更で2つのデータベース間のデータ整合性を確保し、構築している新しい技術(Loose Foreign Keys)を反復することができます。
一般的に、別のクラスターは、データセットのサイズとそれに対応するトランザクションレートの要件が運用コストとその開発をサポートするための追加の複雑さに見合うほど大きい場合にのみサポートされます。当初、これはメインクラスターの一部として別の論理データベースに存在する可能性が高いです。
その他のユースケース
リレーショナル(PostgreSQL)
アプリケーションがメイン RoR アプリケーションコードベースの一部でない場合(例えば Container Registry、Praefect、Geo トラッキングデータベース)、別のデータベースが唯一の選択肢になります。これが論理的なものか独立したクラスターに属するかはスケールによって決まります。
| コードベース | トランザクションレート | ストレージ | データベース |
|---|---|---|---|
| メイン RoR | 低、中 | 低、中 | メインデータベース |
| メイン RoR | 高 | 高(>1TB) | FD データベース |
| 任意 | 低 | 低(<200GB) | 論理データベース |
| 任意 | 中 | 中(<1TB) | 論理データベース |
| 任意 | 高 | 高(>1TB) | 別クラスター |
新しいデータストアエンジン
現在サポートされているデータストアエンジンがアプリケーション要件を満たせなくなり、新しいデータストアエンジンを環境に導入しなければならない場合があります。これは非常にまれなケースですが、一般的に私たちの環境への新しいテクノロジースタックの統合作業(例: 買収)や、データニーズが非常に特殊な場合(例: 時系列)に発生します。
十分な検討には、トレーニング、デプロイメント、設定、メンテナンス(アップグレード)、トラブルシューティングなどの観点から新技術のサポートが様々な作業を必要とするため、できるだけ早くインフラチームを関与させることが含まれます。
