最近、仕事中のアーキテクチャのアップグレードが行われ、元々の EMR クラスタをオープンソースベースの自己構築クラスタに移行しました。そのため、以前使用していたいくつかのコンポーネントも改造する必要があります。その中には S3 も含まれます。私たちの自己構築クラスタでは、オープンソースの Hadoop の S3a クライアント(または S3a コネクタ、以下 S3a と略す)を使用して既存の S3 ストレージに接続しています。次に、S3a クライアントを使用する際にまとめたいくつかの経験を共有します。
S3 プロトコルの種類#
まず、S3 について説明します。S3 は「AWS S3」とも呼ばれ、「AWS Amazon Simple Storage Service」とも呼ばれます。これは、Amazon が開発したオブジェクトストレージサービスであり、広義には Web サービスを含む完全なストレージ製品であり、狭義には AWS のオブジェクトストレージを指すこともできます。S3 は、独自の S3 プロトコルを使用してストレージ上のファイルにアクセスし、そのパスはs3://xxx/yyy/zzz
のようになります。
AWS の市場での地位を考慮すると、S3 ストレージはさまざまな業界で広く使用されています。ただし、S3 プロトコルは AWS のプライベートプロトコルであり、AWS の製品のみが使用できます。S3 の地位を確固たるものにし、ユーザーがどこからでも S3 ストレージに接続し、データを安全に S3 に保存できるようにするために、AWS は S3 に接続するためのオープンソースバージョンの S3 クライアントを Hadoop に提供しています。これがs3n クライアントであり、s3n プロトコル上のファイルパスはs3n://xxx/yyy/zzz
のようになります。
その後、Hadoop は s3n クライアントを廃止し、新しいs3a クライアントを採用しました。s3a プロトコルのファイルパスはs3a://xxx/yyy/zzz
のようになります。
(最初にリリースされた Hadoop の s3 クライアントも s3 プロトコルを採用しており、ファイルパスはs3://
のようになりますが、時代が経ち、既に廃止されているため、ここでは言及しません)
これら 3 つのファイルプロトコルの違いをまとめると次のようになります。
- S3 プロトコルは、AWS の初期であり、プライベートなプロトコルであり、AWS の製品(例:EMR、EC2 など)で広く使用されています。会社が AWS のエコシステムを使用している場合、ほとんどの場合、S3 には S3 プロトコルを使用してアクセスします。
- s3n と s3a は、AWS の S3 SDK をベースにした Hadoop 上のオープンソースの S3 クライアントであり、AWS の S3 ストレージサービスのみを使用し、複数の製品との相互作用が必要なシナリオに適しています。
- パフォーマンスの面では、3 つのプロトコルの違いはほとんどありませんが、S3 は AWS 自体がメンテナンスしているため、バージョンアップの速度がオープンソースの s3n と s3a よりも速い可能性があります。
- 互換性の面では、s3n と s3a は S3 プロトコルと互換性があると言えます。ただし、s3n と s3a の間にはディレクトリの作成に関するいくつかの違いがあります(次のパートで説明します)。特定のシナリオでは注意が必要です。
s3a におけるディレクトリ処理の違い#
実際、多くの人々は S3 をファイルシステムとは見なしていません。したがって、S3 はオブジェクトストレージであり、従来のファイルシステムとは大きく異なると言えます。公式のドキュメントにも次のように記載されています。
Amazon S3 is not a filesystem, it is an object store.
2 つの重要な違いのうちの 1 つは、「ディレクトリ」の概念の解釈です。
- 伝統的な Unix スタイルのファイルシステム(例:HDFS)では、ファイルシステムはディレクトリファイルツリーで構成されており、作成されたディレクトリは「常に存在する」ディレクトリとして扱われます。ディレクトリ内にファイルや他のディレクトリが存在するかどうかに関係なく、いつでも(ディレクトリ内にファイルや他のディレクトリが存在するかどうかに関係なく)ls コマンドを使用してそのディレクトリを確認できます。
- S3 の「ファイルシステム」は、オブジェクトストレージ(またはブロックストレージとも呼ばれる)を使用しているため、「仮想的な」ディレクトリを持っています。例えば、2 つのオブジェクトが同じパスプレフィックスを持つ場合、
a/b/file1
とa/b/file2
、S3 はa/b/
というディレクトリが存在すると見なします。
これらの違いにより、実際の使用中にさまざまな問題が発生する可能性があります。
具体的なシナリオの違い#
さらに具体的なシナリオについて詳しく見てみましょう。
ディレクトリの作成
- HDFS などのディレクトリファイルツリーでは、空のディレクトリを作成し、その中にファイルやディレクトリを追加することができます。また、いつでも(ディレクトリ内にファイルや他のディレクトリが存在するかどうかに関係なく)ls コマンドを使用してそのディレクトリを確認できます。
- 実際には、S3 も同じことができれば、ディレクトリファイルツリーを実現したと見なすことができますが、残念ながらできません。S3 のディレクトリは、プレフィックスを使用してディレクトリを識別するため、ディレクトリ内にファイルが存在しない場合は、ディレクトリマーカー(Directory Marker、以下 DM)を使用してディレクトリをマークする必要があります。ディレクトリにファイルが作成されると、この DM は削除されます。逆に、ディレクトリが空のディレクトリになると、DM が再度追加されます。
- s3a では、空のディレクトリの場合、DM として
path_name+/
という名前のファイルが生成されます。たとえば、mkdir(s3a://bucket/a/b)
を実行すると、マーカーオブジェクトa/b/
が作成されます。 - より古い s3n では、
path_name_$folder$
という形式の DM が使用されます。
- s3a では、空のディレクトリの場合、DM として
ここまでくると、問題が見えてくると思います。例えば、aws s3
コマンドでディレクトリを作成し、s3a で接続しようとすると、通常、ディレクトリが見つからないという問題が発生します。なぜなら、aws s3
ツールで作成されたディレクトリには s3a の DM が作成されていないため、s3a プロトコルではディレクトリが見つからないからです。同様に、クラスタが古いバージョンの Hadoop から新しいバージョンにアップグレードされる場合、空のディレクトリの存在に注意する必要があります。s3n を s3a にアップグレードする際に DM の認識が変わるため、以前の空のディレクトリが検出できなくなる可能性があるからです。
ファイルの作成
- 一般的なディレクトリファイルツリーのファイルシステムでは、ディレクトリのパスに従って単一のファイルを作成するだけです。
- S3 では、ファイルの作成には一連の DM の削除操作が伴う場合があります。s3a は、親ディレクトリのすべての DM を削除するリクエストを含める必要があります。
ディレクトリとファイルの削除
- HDFS のディレクトリファイルツリーでは、ディレクトリの削除操作とファイルの削除操作は基本的に同じです。削除の意味も一般的なロジックに合致しています。
- S3 では、DM の存在により、ファイル / ディレクトリを削除する際に親ディレクトリが空のディレクトリになった場合、DM を追加する必要があります。
問題点#
S3 のディレクトリ処理は、無理な措置であると言えますが、多くの問題の原因となっています。
- s3n と s3a で使用される DM が異なるため、s3a が使用する Hadoop バージョンは下位互換性がないことを意味します。
- s3a でファイルを作成または削除する場合、通常、一連の DM の削除または作成が必要になります。これにより、実際のリクエスト数が増える可能性があります。また、S3 では、各オブジェクトの読み書きが 1 回の操作と見なされるため、大きなオーバーヘッドが発生する可能性があります(S3 の読み書き制限と組み合わせると、S3 のパフォーマンスの低下の主な原因です。詳細は次のセクションで説明します)。
- リスト操作を使用する場合、各リクエストで列挙されるオブジェクトの数は親ディレクトリの数になるため、ディレクトリの階層が深くなるほどリクエストが長くなります。
- 正式なバージョンの S3 バケットでは、オブジェクトが削除されていない場合でも、論理的な削除マーカーがインデックスに書き込まれるため、大規模なディレクトリのクエリが遅くなる可能性があります。
s3a のパフォーマンスの問題#
s3a の公式ドキュメントでは、s3a と HDFS のいくつかの違いが示されています。以下にその一部を引用します:
総じて、次のいくつかの理由が s3a のパフォーマンスの問題を引き起こしています。
- バケットのシャード化により、IOPS が制限されます。
- 異なるタイプの AWS EC2 インスタンスでは、ネットワーク IO に異なる制限がかかる場合があります。
- オブジェクトとデータが多いほど、ディレクトリのリネームやコピー操作にかかる時間が長くなります。rename () のパフォーマンスは特に遅くなります。
- S3 からの読み取り時に seek () 操作を使用すると、新しい HTTP リクエストが強制されます。これにより、Parquet/ORC ファイルの読み取りにかかるコストが増加する可能性があります。
さらに、AWS の S3 は読み書きに制限があるため、一般的な規則によると、1 つのパーティションに対して秒間 5500 回の読み取りまたは 3500 回の書き込みを超えると、S3 はリクエストを拒否し、503 エラーが表示されます。
したがって、大量の読み書きを行う場合、S3 にはまだかなりの課題があることがわかります。ビッグデータ領域で S3 を使用する場合、コストとコストパフォーマンスが重視されます。パフォーマンスを追求する場合は、早く逃げる!
解決策
もちろん、実際のシナリオでは、選択肢が多い場合があります。OLAP やその他の大規模データ処理シナリオで S3 を使用する必要がある場合でも、いくつかの最適化の提案があります。
- s3a コミッターの使用。Hadoop には、S3 ファイルのコミットを最適化するためのさまざまな s3a コミッターが組み込まれており、S3 のマルチパートアップロードメカニズムを使用してファイルのアップロードを高速化するという基本的なアイデアがあります。さまざまなコミッターにはさまざまな最適化アイデアがありますので、詳細はこのドキュメントを参照してください。
- いくつかのパラメータのチューニング、例えばスレッド数や接続数の適切な設定、ブロック読み取りのサイズの増加など
さらなる最適化のシナリオと詳細については、公式ドキュメントを参照してください。
まとめ#
総じて、S3 自体は特定のシナリオでは非常に有利です。AWS エコシステムの重要な一部として、その安全性、信頼性、コストパフォーマンスの向上、および他の AWS クラウド製品との連携による追加の利点が重視されます。ただし、不適切なシナリオで S3 を使用すると、依然として重大な副作用が発生する可能性があることを認識する必要があります。実際のプロダクション環境では、さまざまな妥協要素が存在する場合があり、根本的な解決策を見つけることはできませんが、少なくとも製品の特性を理解し、パフォーマンスを最大限に向上させるための最善の努力をすることができます。
したがって、私は一部の一般的な S3a の落とし穴と対策について簡単に説明しましたが、ほとんどは公式ドキュメントからの整理です。お役に立てれば幸いです〜