Record Layer: FoundationDBによる柔軟性とスケーラビリティの実現

# はじめに

FoundationDBは、高度なスケーラビリティ、堅牢性、および柔軟性を備えた分散型のキーバリューストアです。現在、Apple Inc.によってオープンソースプロジェクトとして広く提供されています。

FoundationDBは、シンプルなキーバリューモデルの基盤であり、従来のデータベースが提供するデータモデルやAPIにあその上位レイヤーでの実現が想定されています。今回は、レイヤーコンセプトの実証例として、公開資料[\[1\]](https://github.com/FoundationDB/fdb-record-layer)[\[2\]](https://dl.acm.org/doi/10.1145/3299869.3314039)を要約する形で、Apple Inc.がCFoundationDBをベースに開発している「Record Layer」を紹介します。

# Record Layerとは?

「Record Layer」はAppleがFoundationDBの上に構築した、リレーショナルデータベースに匹敵する表現力を持つレコード指向のデータストア層です。リレーショナルデータベースのセマンティクスを提供しながら、FoundationDBの強力なトランザクショナルキーバリューストアの上に構築されています。

![techblog_record_layer_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60222/1e6ae670-ee71-255b-7b3c-4890a7c7b406.png)

「Record Layer」は、スキーマ管理、クエリ処理、インデックス作成など、リレーショナルデータベースに期待される多くの機能を提供するだけでなく、ネストされたレコードタイプ、コミットバージョンに対するインデックス、複数のレコードタイプにまたがるインデックスなど、従来のリレーショナルデータベースでは提供されていない高度な機能も提供しています。

## レコード指向とは?

レコード指向とは、従来のリレーショナルデータベースの2次元敵表現に加えり、レコード単位に拡張されたデータ形式を含めてのスキーマが定義可能です。

```

message MySimpleRecord {
  required int64 rec_no = 1 [(com.apple.foundationdb.record.field).primary_key = true];
  optional string str_value_indexed = 2 [(com.apple.foundationdb.record.field).index = {}];
  optional int32 num_value_unique = 3 [(com.apple.foundationdb.record.field).index = { unique: true }];
  optional int32 num_value_2 = 4;
  optional int32 num_value_3_indexed = 5 [(com.apple.foundationdb.record.field).index = {}];
}
```

「リレーショナルデータベースのセマンティクスに似ている」とも表現されていますが、スキーマ定義はProtocol Buffersのメッセージ形式で行われます。

## データ型的な特徴 - 共用/階層型

「Record Layer」でサポートされるデータ型には、従来のリレーショナルデータベースに存在する基本的なプリミティブ型に加え、C言語のUNION形式や階層型(ネスト形式)、特徴的なレコード型の拡張があります。また、Protocol Buffersの仕様にもある、繰り返しデータもタプル型としてサポートされています。

## 特徴的なインデックス - (型 + 式)

「Record Layer」のインデックスは、インデックス型とキー式の組み合わせで定義され、その柔軟性が特徴です。プリミティブ型に加えて、ネスト型やタプル型に対応したConcatenate型のインデックスもサポートされています。キー式には、一意のレコードキーに加えて、ユーザー定義の任意の式も使用可能です。インデックスの更新はレコードの更新と同じトランザクション内で行われるため、データとの強い一貫性が保たれます。

## 問い合わせ方法は？

レコードの問い合わせは、SQLのようなドメイン特有言語ではなく、Protocol Buffers経由で実行されます。JavaベースのユーティリティAPIも提供されており、JavaAPIにてクエリを組み立てて問い合わを行います。

```
RecordQuery query = RecordQuery.newBuilder()
        .setRecordType("myRecord")
        .setFiler(Query.and(
            Query.field("str_field").equalsValue("hello!"),
            Query.field("num_field").greaterThan(10)))
        .setSort(Query.field("rec_no"))
        .build();
 
try (RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(query)) {
  while (cursor.hasNext()) {
    ...
  }
}
```

## マルチテナンシーの実現

「Record Layer」は、マルチテナンシーでの運用を想定して設計されています。各テナントの状態を含むインデックスを別の論理データベースに隔離することで、数億の独立したデータベースをホストすることが可能です。このアーキテクチャは、サービスプロバイダーが膨大な数のユーザーに対して個別のデータストレージと処理能力を提供することを可能にしています。

## 拡張性とカスタマイズ性

「Record Layer」は、その拡張性においても特徴的です。クライアント定義のインデックスタイプ、暗号化、圧縮アルゴリズムなど、アプリケーションの特定の要件に合わせてライブラリをカスタマイズすることが可能です。この高度なカスタマイズ性により、開発者はアプリケーションのパフォーマンスを最適化し、ユーザーに最高の体験を提供しています。

# 最後に

「Record Layer」は、FoundationDBのレイヤコンセプトに沿って構築された、リレーショナルデータベースの機能と柔軟性を融合したデータストアです。「Record Layer」による実証は、高度なスケーラビリティ、堅牢性、および柔軟性を備えた分散型のキーバリューストアであるFoundationDBの可能性を示すものでしょう。

# 参考資料
- [\[1\] FoundationDB Record Layer](https://github.com/FoundationDB/fdb-record-layer)
- [\[2\] hrysafis, Christos, et al. "Foundationdb record layer: A multi-tenant structured datastore." Proceedings of the 2019 International Conference on Management of Data. 2019.](https://dl.acm.org/doi/10.1145/3299869.3314039)