Delta Lake は、Lakehouse アーキテクチャのオブジェクト ストレージ上にデータ レイクを構築するために使用されるオープンソース ストレージ フレームワークです。 Delta Lake は、ACID トランザクション、スケーラブルなメタデータ処理、統合ストリーミングおよびバッチ データ処理をサポートしています。 Delta Lake は、Apache Spark アプリケーションに信頼性、一貫性、およびスケーラビリティを提供するために一般的に使用されます。 Delta Lake は、MinIO などの既存のデータ レイク ストレージの上で実行され、Apache Spark API と互換性があります。
Delta Lake のオリジナルの論文 ( Delta Lake: High-Performance ACID Table Storage over Cloud Object Stores ) では、Delta Lake がクラウド オブジェクト ストレージ用にどのように構築されたかについて説明しています。 Vertica が外部テーブルに対する Delta Lake の使用をテストしたとき、MinIO に依存していました。 HPE Ezmeral Runtime Enterprise の顧客はMinIO で Delta Lake を実行します。 MinIO は、分散モードとスタンドアロン モードの両方で、すべての I/O 操作に対して厳密な書き込み後読み取りおよび書き込み後リストの一貫性モデルに従っており、Delta Lake ワークロードを実行することが広く認められているため、Delta Lake の耐久性要件をサポートしています。
多くの組織は、大規模な構造化データセット、半構造化データセット、非構造化データセットを格納するために、MinIO や AWS S3 などのクラウド ネイティブ オブジェクト ストアに依存しています。各テーブルは、Parquet または ORC であるオブジェクトのセットとして格納され、パーティションに配置されます。大きなファイルに対するクエリは、基本的には高速に実行されるスキャンです。
Delta Lake がないと、より複雑な Spark ワークロード、特にデータの変更、追加、削除を行うワークロードは、マルチユーザー/マルチアプリの負荷が重い場合、パフォーマンスと正確性が課題に直面します。複数オブジェクトの更新はアトミックではなく、クエリは分離されていません。つまり、1 つのクエリで削除が実行されると、元のクエリが各オブジェクトを更新するため、他の同時クエリでは部分的な結果が得られます。書き込みのロールバックは難しく、更新中にクラッシュするとテーブルが破損する可能性があります。本当のパフォーマンスのキラーはメタデータです。数十億または数兆のレコードを保持する Parquet ファイルである数百万のオブジェクトを含む大規模なテーブルの場合、メタデータ操作により、データ レイク上に構築されたアプリケーションが停止する可能性があります。
Delta Lake は、データベースのトランザクションの信頼性とデータ レイクの水平スケーラビリティを組み合わせるように設計されました。 Delta Lake は、MinIO などのクラウド ネイティブ オブジェクト ストア上の ACID テーブル ストレージ レイヤーを使用して、OLAP スタイルのワークロードをサポートするように構築されました。論文「Delta Lake: クラウド オブジェクト ストア上の高性能 ACID テーブル ストレージ」で説明されているように、「Delta Lake の中心的なアイデアはシンプルです。どのオブジェクトが Delta テーブルの一部であるかに関する情報を、書き込みそれ自体はクラウド オブジェクト ストアに保存される先行ログです。」オブジェクトは Parquet でエンコードされ、Parquet を理解するエンジンで読み取ることができます。複数のオブジェクトを「シリアル化された方法で同時に」更新でき、同時に高い並列読み取りおよび書き込みパフォーマンスを実現できます。ログには各ファイルの最小/最大統計などのメタデータが含まれており、オブジェクト ストア内のファイルを直接検索するよりも「桁違いに高速なメタデータ検索が可能」になります。
デルタ湖では次のものが提供されます。
レイクハウス アーキテクチャ、特に Delta Lake は、オブジェクト ストレージ上に構築されたデータ レイクに重要な新機能をもたらします。 Delta Lake は、Spark、Starburst、Trino、Flink、Hive など、ますます増え続けるアプリケーションやコンピューティング エンジンのリストで動作し、Scala、Java、Rust、Ruby、Python の API も含まれています。クラウド向けに構築された Kubernetes ネイティブ MinIO は、エッジ、データセンター、パブリック/プライベート クラウドなど、あらゆる場所でパフォーマンスと復元力に優れた安全なデータ レイク アプリケーションを実現します。
デルタ テーブルは、ディレクトリ (ファイル システムの場合) またはバケット (MinIO およびその他のオブジェクト ストレージの場合) にまとめて保存されるファイルのコレクションです。オブジェクト ストレージから読み書きするために、Delta Lake はパスのスキームを使用してストレージ システムを動的に識別し、対応する LogStore 実装を使用して ACID 保証を提供します。 MinIO の場合は、S3A を使用します。 「ストレージ構成 — Delta Lake ドキュメント」を参照してください。 Delta Lake に使用される基盤となるストレージ システムが、MinIO と同様にアトミックな読み取り/書き込みを同時に実行できることが重要です。
デルタ テーブルの作成とは、実際にはファイルをディレクトリまたはバケットに書き込むことです。デルタ テーブルは、Spark DataFrame を書き込み (読み取り)、 delta
形式とパスを指定することによって作成 (オープン) されます。 Scala では、たとえば次のようになります。
// Create a Delta table on MinIO: spark.range(5).write.format("delta").save("s3a://<your-minio-bucket>/<path-to-delta-table>") // Read a Delta table on S3: spark.read.format("delta").load("s3a://<your-mnio-bucket>/<path-to-delta-table>").show()
Delta Lake はテーブルごとのバケットに依存しており、バケットは通常、ファイル システム パスに基づいてモデル化されています。 Delta Lake テーブルは、データ、メタデータ、トランザクション ログを含むバケットです。テーブルは Parquet 形式で保存されます。テーブルは複数のファイルに分割できます。 MinIO は、ファイル システム スタイルのパスを使用してオブジェクトを効率的にリストするための S3 LIST をサポートしています。 MinIO は、大きな Parquet ファイルのサブセットをより効率的に読み取るために、バイト範囲リクエストもサポートしています。
MinIO は、業界をリードするパフォーマンスにより、Delta Lake テーブルに最適です。 MinIO のスケーラビリティとハイパフォーマンスの組み合わせにより、要求がどれほど厳しいかに関係なく、あらゆるワークロードを手の届く範囲に収めることができます。 MinIO は驚異的なパフォーマンスを実現します。最近のベンチマークでは、わずか 32 ノードの既製 NVMe SSD で GET で 325 GiB/s (349 GB/s)、PUT で 165 GiB/s (177 GB/s) を達成しました。 MinIO は、Delta Lake 上の最も要求の厳しいワークロードに電力を供給するのに必要なパフォーマンスを十分に発揮します。
Delta Lake バケットには多くの Parquet ファイルと JSON ファイルが含まれる可能性が高く、これはデータ レイクとして使用するために MinIO に組み込まれたすべての小さなファイルの最適化と非常によく調和します。小さなオブジェクトはメタデータとともにインラインで保存されるため、Delta Lake トランザクションのような小さなファイルの読み取りと書き込みの両方に必要な IOPS が削減されます。
ほとんどの企業は、Delta Lake にマルチクラウド機能を必要とします。 MinIO には、オンプレミス、パブリック/プライベート クラウド、エッジの場所間でデータを同期するためのアクティブ/アクティブ レプリケーションが含まれています。アクティブ/アクティブ レプリケーションにより、企業は複数地域の復元力と高速なホット/ホット フェイルオーバーを設計できます。各バケットまたは Delta Lake テーブルは、セキュリティと可用性を最大限に高めるために個別にレプリケーションを構成できます。
ACID (原子性、整合性、分離性、耐久性) トランザクションをデータ レイクに追加することは、非常に重要なことです。なぜなら、組織はデータ レイクに保存されている大量のデータをより詳細に制御できるようになり、そのため信頼性が高まるからです。以前は、Spark に依存してデータ レイクを操作していた企業にはアトミック API と ACID トランザクションが不足していましたが、現在では Delta Lake によってそれが可能になっています。データはキャプチャおよび書き込み後に更新でき、ACID のサポートにより、操作中にアプリケーションに障害が発生してもデータは失われません。 Delta Lake は、データの読み取りと書き込みのために Spark と MinIO の間の仲介者として機能することでこれを実現します。
Delta Lake の中心となるのは、ユーザーとアプリケーションによって実行されたトランザクションの順序付けされた記録であるDeltaLogです。ユーザーが Delta Lake テーブルに対して実行するすべての操作 (UPDATE や INSERT など) は、複数のアクションまたはジョブで構成されるアトミック コミットです。すべてのアクションが正常に完了すると、コミットがエントリとして DeltaLog に記録されます。いずれかのジョブが失敗した場合、コミットは DeltaLog に記録されません。アトミック性がないと、ハードウェアまたはソフトウェアに障害が発生し、データが部分的にしか書き込まれずにデータが破損する可能性があります。
Delta Lake は、操作を次の 1 つ以上のアクションに分割します。
ファイルを追加 - ファイルを追加します
ファイルを削除 - ファイルを削除します
メタデータの更新 - テーブルの名前、スキーマ、またはパーティショニングへの変更を記録します。
トランザクションの設定 - ストリーミング ジョブがデータをコミットしたことを記録します
コミット情報 - 操作、ユーザー、時間などのコミットに関する情報
プロトコルの変更 - DeltaLog を最新のソフトウェア プロトコルに更新します
見た目ほど複雑ではありません。たとえば、ユーザーがテーブルに新しい列を追加し、そこにデータを追加すると、Delta Lake はそれをコンポーネントのアクションに分割し、メタデータを更新して列を追加し、新しいファイルが追加されるたびにファイルを追加します。完了すると DeltaLog が記録されます。
Delta Lake は、オプティミスティック同時実行制御を利用して、特定のテーブルの複数のリーダーとライターがテーブル上で同時に作業できるようにします。オプティミスティック同時実行制御では、異なるユーザーによって行われたテーブルへの変更が競合することなく完了できることを前提としています。データの量が増えると、ユーザーが別のテーブルで作業する可能性も高くなります。 Delta Lake はコミットをシリアル化し、2 つ以上のコミットが同時に発生した場合には相互排他ルールに従います。そうすることで、Delta Lake は ACID に必要な分離を実現し、複数の同時書き込み後のテーブルは、それらの書き込みが連続して別々に行われた場合と同じように見えます。
前回の読み取り以降に変更された開いているテーブルに対してユーザーが新しいクエリを実行すると、Spark は DeltaLog を参照して、新しいトランザクションがテーブルにポストされたかどうかを判断し、それらの新しい変更でユーザーのテーブルを更新します。これにより、テーブルのユーザーのバージョンが Delta Lake のマスター テーブルと最新の操作に同期され、ユーザーがテーブルに対して競合する更新を行うことができなくなります。
DeltaLog、オプティミスティック同時実行制御、スキーマ強制 (スキーマを進化させる機能と組み合わせる) により、アトミック性と一貫性の両方が保証されます。
ユーザーが Delta Lake テーブルを作成すると、そのテーブルのトランザクション ログが_delta_log
サブディレクトリに自動的に作成されます。ユーザーがテーブルを変更すると、各コミットは JSON ファイルとして_delta_log
サブディレクトリに昇順で書き込まれます (つまり、 000000.json
、 000001.json
、 000002.json
など)。
データ ファイル1.parquet
および2.parquet
からテーブルに新しいレコードを追加するとします。そのトランザクションは DeltaLog に追加され、ファイル000000.json
として保存されます。後で、これらのファイルを削除し、代わりに新しいファイル3.parquet
を追加します。これらのアクションは、新しいファイル000001.json
として記録されます。
1.parquet
と2.parquet
を追加した後、それらを削除しました。トランザクション ログには、両方の操作が互いに否定されている場合でも、両方の操作が含まれます。 Delta Lake はすべてのアトミック コミットを保持し、完全な監査履歴と、特定の時点でテーブルがどのように見えたかをユーザーに示すタイム トラベル機能を有効にします。さらに、 VACUUMジョブが実行されるまで、ファイルはストレージからすぐには削除されません。 MinIO のバージョン管理により、誤った削除に対するもう 1 つの保証層が提供されます。
Delta Lake は、テーブルとトランザクション ログを永続メディアに保存することで耐久性を実現します。ファイルは上書きされないため、積極的に削除する必要があります。ストレージに書き込まれたすべてのデータ変更は、発生時にアトミックにユーザーに利用可能です。部分的なファイルや破損したファイルは過去のものになります。 Delta Lake はテーブルとログを RAM に長時間保持せず、それらを MinIO に直接書き込みます。コミット データが DeltaLog に記録され、JSON ファイルがバケットに書き込まれている限り、システムまたはジョブのクラッシュが発生した場合でもデータは持続します。
MinIO は、テーブルとそのコンポーネントが複数のメカニズムを通じて書き込まれた後の耐久性を保証します。
MinIO は、暗号化を使用して Delta Lake テーブルを保護し、IAM とポリシーベースのアクセス制御の組み合わせを使用してテーブルへのアクセスを規制します。 MinIO は、転送中のデータを TLS で暗号化し、ドライブ上のデータを、AES-256-GCM、ChaCha20-Poly1305、AES-CBC などの最新の業界標準暗号化アルゴリズムを使用した詳細なオブジェクト レベルの暗号化で暗号化します。 MinIO は、ActiveDirectory/LDAP、Okta、IAM 用の Keycloak などの外部ID プロバイダーと統合します。ユーザーとグループは、Delta Lake テーブルにアクセスしようとすると、AWS IAM 互換の PBAC の対象になります。
このセクションでは、単一クラスター モードを使用して MinIO でデルタ テーブルの読み取りと書き込みを迅速に開始する方法について説明します。
/home/spark
など) にコピーできます。hadoop-aws-2.6.5.jar
- Delta Lake には、S3 用の Hadoop のFileSystem
API を実装するhadoop-aws
パッケージのorg.apache.hadoop.fs.s3a.S3AFileSystem
クラスが必要です。このパッケージのバージョンが、Spark が構築された Hadoop のバージョンと一致していることを確認してください。aws-java-sdk-1.7.4.jar
Delta Lake で Spark シェル (Scala または Python) を起動し、コード スニペットを対話的に実行します。
スカラの場合:
bin/spark-shell --packages io.delta:delta-core_2.12:1.2.1 --conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" --conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog"
次のコマンドを実行して、Delta Lake と S3 の MinIO サポートを備えた Spark シェルを起動します。
bin/spark-shell \ --packages io.delta:delta-core_2.12:1.2.1,org.apache.hadoop:hadoop-aws:3.3.1 \ --conf spark.hadoop.fs.s3a.access.key=<your-MinIO-access-key> \ --conf spark.hadoop.fs.s3a.secret.key=<your-MinIO-secret-key> --conf "spark.hadoop.fs.s3a.endpoint=<your-MinIO-IP:port> \ --conf "spark.databricks.delta.retentionDurationCheck.enabled=false" \ --conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" \ --conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog"
MinIO クライアントを使用して、Delta Lake のバケットを作成します。
mc alias set minio http://<your-MinIO-IP:port> <your-MinIO-access-key> <your-MinIO-secret-key> mc mb minio\delta-lake
試してみて、Scala を使用して単純な Delta Lake テーブルを作成します。
// Create a Delta table on MinIO: spark.range(500).write.format("delta").save("s3a://delta-lake/demo1")
Spark がテーブルを正常に書き込んだことを示す出力が表示されます。
ブラウザを開いて、アクセス キーと秘密キーを使用してhttp://<your-MinIO-IP:9001>
にある MinIO にログインします。バケット内に Delta Lake テーブルが表示されます。
MinIO と Delta Lake を組み合わせることで、企業は統合された単一の信頼できる情報源として機能するマルチクラウド データ レイクを構築できるようになります。 Delta Lake テーブルのクエリと更新機能により、企業は自社のビジネスと顧客に関する豊富な洞察を得ることができます。さまざまなグループが、自分たちの作業が安全でデータがタイムリーであることを認識しながら、独自の分析や機械学習の取り組みのために Delta Lake テーブルにアクセスします。
さらに詳しく知りたい場合は、 MinIO をダウンロードして自分の目で確認するか、パブリック クラウド上でマーケットプレイス インスタンスを起動してください。質問ありませんか? Slackまたは [email protected] 経由で質問してください。
ここでも公開されています。