分散システムエンジニアのためのATProto

Sep 3, 2024

AT プロトコルは、オープン ソーシャル ネットワーキング向けに Bluesky で開発された技術です。この記事では、分散バックエンド エンジニアリングの観点から AT Proto について説明します。

ストリーム処理 を使用してバックエンドを構築したことがある場合は、これから説明するシステムの種類に精通していることになります。そうでない場合は、心配しないでください。手順を追って説明します。

従来の Web バックエンドのスケーリング

従来の、使いやすい Web アーキテクチャは、アプリ サーバーの背後にある「1 つの大きな SQL データベース」です。アプリはデータベースと通信し、フロントエンドからのリクエストを処理します。

アプリケーションが大きくなるにつれて、パフォーマンスの限界に達するため、スタックにキャッシュをいくつか投入します。

次に、シャーディングとレプリカを使用してデータベースを水平方向にスケーリングするとします。

これはかなり良いですが、何億人ものユーザーを抱えるソーシャル ネットワークを構築しているため、このモデルでも限界に達します。問題は、SQL データベースが「強い一貫性」であることです。つまり、状態はシステム全体で均一に同期されています。強い一貫性を維持するとパフォーマンス コストが発生し、それがボトルネックになります。

システムを緩和して「最終的な一貫性」を使用できれば、さらに拡張できます。まず、NoSQL クラスターに切り替えます。

これは拡張には適していますが、SQL がないとクエリの構築が難しくなります。SQL データベースには、JOIN や集計クエリなど、多くの便利な機能があることがわかりました。実際、NoSQL データベースは単なるキー値ストアです。機能の作成は面倒になってきています。

これを修正するには、データセットの事前計算済みビューを生成するプログラムを作成する必要があります。これらのビューは、本質的にはキャッシュされたクエリのようなものです。これらのビューに標準データを複製して、非常に高速にします。

これらをビュー サーバーと呼びます。

ここで、ビュー サーバーを NoSQL クラスター内の正規データと同期させ続けるのは難しいことに気が付きました。ビュー サーバーがクラッシュして更新が失われることがあります。ビューが確実に最新の状態に保たれるようにする必要があります。

この問題を解決するために、イベント ログ (Kafka など) を導入します。このログは、NoSQL クラスターへのすべての変更を記録してブロードキャストします。ビュー サーバーは、再起動が必要な場合でも更新を見逃さないように、このログをリッスンして再生します。

これで ストリーム処理アーキテクチャ に到達しました。さらに詳しく説明できる点はたくさんありますが、今のところはこれで十分です。

良いニュースは、このアーキテクチャの拡張性が非常に高いことです。 強力な一貫性はあきらめ、読み取りクエリがデータの最新バージョンより遅れることもありますが、サービスが書き込みをドロップしたり、誤った状態になったりすることはありません。

ある意味、私たちが行ったのは データベースを裏返しにして、データベースをカスタム構築したことです。 標準ストレージを NoSQL クラスターに簡素化し、ビュー サーバーを使用して独自のクエリ エンジンを構築しました。 構築の利便性は大幅に低下しますが、拡張性があります。

大規模バックエンドの分散化

AT プロトコルの目標は、アプリケーションを相互接続して、バックエンドがユーザー アカウントやコンテンツなどの状態を共有することです。

どうすればそれができるでしょうか。図を見ると、システムの大部分が外部から分離されており、App サーバーのみがパブリック インターフェイスを提供していることがわかります。

私たちの目標は、この分離を解消して、他の人が NoSQL クラスター、イベント ログ、ビュー サーバーなどに参加できるようにすることです。

次のようになります。

これらの内部サービスはそれぞれ外部サービスになりました。これらには、誰でも使用できるパブリック API があります。さらに、誰でもこれらのサービスの独自のインスタンスを作成できます。

私たちの目標は、誰もがこの分散型バックエンドに貢献できるようにすることです。つまり、1 つの NoSQL クラスターや 1 つの View サーバーだけが必要なわけではありません。多数のサーバーが連携して動作することが必要です。したがって、実際には次のようになります。

では、これらすべてのサービスを連携させるにはどうすればよいでしょうか?

データ モデルの統合

“ユーザー データ リポジトリ” と呼ばれる共有データ モデルを確立します。

すべてのデータ リポジトリには、JSON ドキュメント (ここでは “レコード” と呼びます) が含まれます。

整理のため、これらのレコードを「コレクション」にまとめます。

次に、NoSQL サービスに意見を表明して、すべてのサービスがこの データ リポジトリ モデルを使用するようにします。

覚えておいてください: データ リポジトリ サービスは基本的に NoSQL ストアのままですが、非常に特殊な方法で整理されるようになりました:

  1. 各ユーザーにはデータ リポジトリがあります。

  2. 各リポジトリにはコレクションがあります。

  3. 各コレクションは、JSON ドキュメントの順序付けられた K/V ストアです。

データ リポジトリは誰でもホストできるため、URL を指定する必要があります。

ついでに、レコード用の URL スキーム全体 も作成しましょう。

すばらしい! また、これらのレコードをインターネット上で同期するため、本物であることを確認するために暗号署名することをお勧めします。

データの流れを図に表す

大規模な分散型バックエンドをセットアップしたので、ATProto でアプリケーションが実際にどのように動作するかを図にしてみましょう。

新しいアプリを作成するので、2 つのものが必要になります。アプリ サーバー (API とフロントエンドをホスト) とビュー サーバー (ネットワークからデータを収集する) です。アプリ サーバーとビュー サーバーはバンドルされることが多いため、単に「Appview」と呼ぶことができます。まずはそこから始めましょう。

ユーザーは OAuth を使用してアプリにログインします。その過程で、ユーザーはデータ リポジトリをホストするサーバーを私たちに伝え、そして それを読み書きする権限を私たちに与えます。

順調なスタートです。ユーザーのリポジトリで JSON ドキュメントを読み書きできます。他のアプリ (プロファイルなど) から既にデータがある場合は、そのデータも読み取ることができます。シングルプレイヤー アプリを作成している場合は、すでに完了しています。

ただし、JSON ドキュメントを書き込むと何が起こるかを図にしてみましょう。

これにより、ドキュメントがリポジトリにコミットされ、リポジトリをリッスンしているイベント ログへの書き込みが開始されます。

そこから、イベントはリッスンしているすべてのビュー サービスに送信されます。これには、私たち自身のサービスも含まれます。

書き込みを行っているのに、なぜイベント ストリームをリッスンしているのでしょうか。書き込みを行っているのは私たちだけではないからです。イベントを生成するユーザー リポジトリは多数あり、それらに書き込むアプリも多数あります。

このように、分散バックエンド全体で一種の循環データ フローが見られます。書き込みはデータ リポジトリにコミットされ、イベント ログを通じてビュー サーバーに送信され、アプリケーションで読み取ることができます。

そして、このネットワークが拡張され続けることを願っています。容量を増やすだけでなく、このオープン アプリケーション ネットワークで共有されるアプリケーションの多様性を高めるためです。

実用的なオープン システムの構築

AT プロトコルは、P2P テクノロジと大規模システムの実践を融合します。当社の創設エンジニアは、IPFS および Dat のコア エンジニアであり、Data Intensive Applications の著者である Martin Kleppmann は、アクティブな技術アドバイザーです。

Bluesky を始める前に、私たちは「後退しない」という明確な要件を設定しました。ネットワークが、これまでのすべてのソーシャル アプリと同様に便利でグローバルでありながら、オープン ネットワークとして機能することを望んでいました。そのため、フェデレーションとブロックチェーンを検討したときに、これらのアーキテクチャのスケーリングの限界が際立っていました。私たちの解決策は、大規模なバックエンドの標準的な方法を採用し、ピアツーピア システムで使用した手法を適用してオープン ネットワークを作成することでした。

詳細を知りたいですか?

仕様、ガイド、SDK は、こちらでご覧いただけます。