【ビッグデータHadoop】HDFS3.3.1-Datanode-DataStorageの実装原理

序文

Datanode の最も重要な機能は、ディスクに保存されている HDFS データ ブロックを管理することです。Datanode は、この管理機能を 2 つの部分に分割します: ① current、previous、detach、tmp などのディスク ストレージ ディレクトリ (dfs.data.dir で指定) を管理および整理し、この機能は DataStorage クラスによって実現されます。データ ブロックとそのメタデータ ファイルを管理および整理するこの機能は、主に FsDatasetlmpl の関連クラスによって実現されます。このセクションでは、DataStorage クラスの実装について説明します。

ストレージクラスの継承関係

Data Storage の親クラスは Storage であり、Storage クラスの継承関係を次の図に示します。StorageInfo はルート インターフェイスであり、ストレージの基本情報が記述されます。サブクラス Storage は抽象クラスであり、Datanode および Namenode に抽象ストレージ サービスを提供します。

ここに画像の説明を挿入

Storage は複数のストレージ ディレクトリを定義できます。ストレージ ディレクトリは、Storage 内部クラス StorageDirectory によって記述されます。StorageDirectory クラスは、ストレージ ディレクトリに対する共通の操作を定義します。ここでは Datanode の構成を例に挙げます。Datanode はデータ ブロックを保存するために複数のストレージ ディレクトリを定義できます。次の構成に示すように、Datanode は 2 つのデータ ストレージ ディレクトリ、つまり /data/hdfs/dfs/data と "/data" を定義します。 /hdfs /afs/data2"。HDFS は Data Storage オブジェクトを使用して Datanode 全体のストレージを管理し、これら 2 つのストレージ ディレクトリは 2 つの StorageDirectory オブジェクトによって管理されます。

<property>
  <name>dfs.data.dir</name>
  <value>[DISK]/data/hdfs/data_1,[SSD]/data/hdfs/data_2</value>
</property>

フェデレーション メカニズムにより、Datanode は複数のブロック プールを管理します。HDFS は、Datanode 上のブロック プールを管理するために BlockPoolSliceStorage クラスを定義します。ブロック プールは、Datanode によって構成されたすべてのストレージ ディレクトリに分散されます。DataStorage クラスは、すべての BlockPoolSliceStorage オブジェクトへの参照を保持し、これらの参照を通じて Datanode 上のすべてのブロック プールを管理します。

ストレージ情報

StorageInfo はストレージの基本情報を記述するクラスであり、以下の 5 つのフィールドを持ちます。

  • レイアウト バージョン: ストレージ システム レイアウト バージョン番号。ノード ストレージのディレクトリ構造が変更されるか、fsimage と editlog の形式が変更されると、ストレージ システム レイアウト バージョン番号が更新されます。このバージョン番号は通常、負の数です。
  • namespaceID: ストレージ システムの名前空間識別子。
  • cTime: ストレージ システムの作成時間。
  • [clusterID]: ストレージ システムのクラスタ ID。
  • storageType: データ ノード、ネーム ノード、ジャーナル ノードなどを含むノード タイプ。

ここで、StorageInfoに定義された情報は、ストレージディレクトリのVERSIONファイルに格納されることに注意してください。VERSIONファイルは、Javaの代表的なProperties(プロパティ)ファイルです。上記の5つのプロパティに加えて、さまざまな種類のVERSIONファイルが格納されています。ノードには他の固有のプロパティも格納されます。

storagelnfo メソッドのほとんどは get/set メソッドであり、Properties ファイルからプロパティを読み取ってフィールドを割り当てる方法は比較的単純なので、ここでは詳しく説明しません。

ストレージ.ストレージ状態

Storage クラスは、非常に重要な内部列挙クラス、StorageState を定義します。これは、ストレージ スペースのすべての可能な状態を完全に定義します。アップグレード、ロールバック、アップグレードの送信、チェックポイントなどの操作中に、ノード (Datanode または Namenode) のストレージ領域に誤操作、停電、ダウンタイムなどのさまざまな異常が発生する可能性があります。 HDFS がエラーから回復するのに有益な中間状態が導入されます。ストレージ状態の決定は、StorageDireetory.analyseStorage0) メソッドで実行されます。これについては、次のセクション StorageDirectory で説明します。

  public enum StorageState {
    
    
    NON_EXISTENT, //  存储不存在
    NOT_FORMATTED,  //  存储未格式化
    COMPLETE_UPGRADE, //  完成升级
    RECOVER_UPGRADE,  //  恢复升级
    COMPLETE_FINALIZE,  //  完成升级提交
    COMPLETE_ROLLBACK,  //  完成回滚操作
    RECOVER_ROLLBACK, //  恢复回滚
    COMPLETE_CHECKPOINT,  //  完成检查点操作
    RECOVER_CHECKPOINT, //  恢复检查点操作
    NORMAL; //  正常状态
  }

ここでは特別な注意を払う必要があります。ストレージの状態は、HdfsServerConstants クラスに保存される起動オプションにも関連します。コードは次のとおりです。

  enum StartupOption{
    
    
    FORMAT  ("-format"), // 格式化操作
    CLUSTERID ("-clusterid"),	// 获取集群ID
    GENCLUSTERID ("-genclusterid"), // 生成集群ID
    REGULAR ("-regular"),	// 正常启动
    BACKUP  ("-backup"),	// 备份
    CHECKPOINT("-checkpoint"),	// 
    UPGRADE ("-upgrade"),	//	升级
    ROLLBACK("-rollback"),	//	回滚
    ROLLINGUPGRADE("-rollingUpgrade"),	//	滚动升级
    IMPORT  ("-importCheckpoint"),	//
    BOOTSTRAPSTANDBY("-bootstrapStandby"),
    INITIALIZESHAREDEDITS("-initializeSharedEdits"),
    RECOVER  ("-recover"),
    FORCE("-force"),
    NONINTERACTIVE("-nonInteractive"),
    SKIPSHAREDEDITSCHECK("-skipSharedEditsCheck"),
    RENAMERESERVED("-renameReserved"),
    METADATAVERSION("-metadataVersion"),
    UPGRADEONLY("-upgradeOnly"),
    // The -hotswap constant should not be used as a startup option, it is
    // only used for StorageDirectory.analyzeStorage() in hot swap drive scenario.
    // TODO refactor StorageDirectory.analyzeStorage() so that we can do away with
    // this in StartupOption.
    HOTSWAP("-hotswap"),
    // Startup the namenode in observer mode.
    OBSERVER("-observer");
    // ...
  }

ストレージ.ストレージディレクトリ

Datanode と Namenode の両方がデータを保存するために複数のストレージ ディレクトリを定義できることはわかっています。StorageDirectory は Storage の内部クラスであり、ストレージ ディレクトリを管理するための共通メソッドを定義します。

  • root: ストレージ ディレクトリのルート (java.io.File ファイル)。
  • dirType: 現在のストレージ ディレクトリのタイプ。
  • isShared: 現在のディレクトリが共有されているかどうかを示します。たとえば、HA デプロイメントでは、ストレージ ディレクトリは、異なるネームノード間、またはフェデレーション デプロイメント内の異なるブロック プール間で共有されます。
  • lock: 排他ロック、java.nio.FileLock タイプ。Datanode または Namenode スレッドの排他的ストレージ ディレクトリのロック操作をサポートするために使用されます。
  • storageUuid: ストレージ ディレクトリの識別子。

StorageDirectory のメソッドは主に、フォルダ関連操作の取得、ロック/ロック解除操作、ストレージ状態の復元操作の 3 つに分類されます。これら 3 種類のメソッドの実装を順番に見てみましょう。

フォルダ操作

現在のストレージ ディレクトリ構造内の各ファイル/フォルダーを取得する方法。HDFS アップグレード プロセスに関係するすべてのディレクトリは、StorageDirectory が提供するメソッドを通じて取得できます。

ここに画像の説明を挿入

  • getCurrentDir() - 現在のディレクトリを取得します。
  • getVersionFile() —— 現在のディレクトリにある VERSION ファイルを取得します。
  • getPreviousDir() - 前のディレクトリを取得します。
  • getPrevious VersionFile() - 前のディレクトリにある VERSION ファイルを取得します。
  • getPreviousTmp() -Previous.tmp ディレクトリを取得します。
  • getRemovedTmp() - Removed.tmp ディレクトリを取得します。
  • getFinalizedTmp() - Finalized.tmp ファイルを取得します。
  • getLastCheckpointTmp() - lastcheckpoint.tmp ファイルを取得します。
  • getPreviousCheckpoint() -Previous.checkpoint ファイルを取得します。

ロック/アンロック操作

Datanode ディスク ストレージ構造のセクションでは、ストレージ ディレクトリの下に in_use.lock ファイルが存在し、j ファイルを使用して現在のストレージ ディレクトリをロックし、Datanode プロセスによるストレージ ディレクトリの排他的使用を保証することを紹介しました。in_use.lock ファイルは、Datanode プロセスの実行が終了すると削除されます。StorageDirectory には、tryLock0 とunlock0 という 2 つのロック メソッドが用意されており、それぞれストレージ ディレクトリのロックとロック解除の機能を実現します。

StorageDirectory での実際のロック操作は tryLockO メソッドです。tryLockO メソッドは、最初にロック ファイルを構築し、次に file.getChannel.lockO メソッドを呼び出して、ストレージ ディレクトリの排他的ロックを取得しようとします。プロセスがすでにロック ファイルを所有している場合は、file.getChannel.lock( が返されます) null 参照 (別のノードがあることを示す) 現在のストレージ ディレクトリでノードが実行されている場合、tryLockO メソッドは例外をスローして実行を終了します。ロックが成功すると、tryLockO メソッドは仮想マシン情報をロック ファイルに書き込みます。 。

ストレージ状態の復元操作

Datanode 上でアップグレード、ロールバック、コミット操作を実行する過程で、誤操作、停電、ダウンタイムなど、さまざまな異常が発生します。では、Datanode は再起動時に最後に中断された操作をどのように再開するのでしょうか? StorageDirectory には、 doRecover() とanalyzeStorage( という 2 つのメソッドが用意されています。Datanode は、まず、analyzeStorage( メソッドを呼び出して現在のノードのストレージ ステータスを分析し、次に doRecover( メソッドを呼び出して、分析されたストレージ ステータスに従ってリカバリ操作を実行します)。

保管所

Storage は、Datanode と Namenode に抽象ストレージ サービスを提供する抽象クラスです。Storage クラスは、現在のノード (Datanode または Namenode の場合があります) 上のすべてのストレージ ディレクトリを管理します。各ストレージ ディレクトリは、StorageDirectory オブジェクトによって管理されます。ストレージは、線形テーブル フィールド storageDirs を使用して、管理するすべての StorageDirectorv を保存し、Dirlterator を反復処理します。イテレータのトラバース。

データストレージ

DataStorage は、Storage 抽象クラスを継承し、Datanode ストレージ領域を管理する機能を提供します。このセクションでは、DataStorage クラスの実装について説明します。

HDFSFederation アーキテクチャでは、データノードは複数のネームスペースのデータ ブロックを保存でき、各ネームスペースにはデータノード ディスク上に独立したブロック プール (BlockPool) があります。このブロック プールは、データノードのすべてのストレージ ディレクトリに分散されます。現在のデータノード上のこのブロック プールはまとめて保存されます。HDFS は、Datanode 上の単一ブロック プールの記憶域スペースを管理する BlockPoolSliceStorage クラスを定義し (BlockPoolSliceStorage の実​​装については次のセクションで紹介します)、DataStorage クラスは、すべてのブロック プール BlockPoolSliceStorage オブジェクトの参照を保存する bpStorageMap フィールドを定義します。データノード。次のコードに示すように、bpStorageMap フィールドは Map タイプであり、bpld->BlockPoolSliceStorage のマッピング関係を維持します。

private final Map<String, BlockPoolSlicestorage> bpstorageMap = Collections.synchronizedMap (new HashMap<String, BlockPoolSlicestorage>());

Datanode が起動すると、DataStorage が提供するメソッドを呼び出して Datanode のストレージ領域を初期化し、HDFS フェデレーション アーキテクチャでは、Datanode は複数の名前空間のデータ ブロックを保存します。ネームスペースごとに、Datanode は BPOfferService クラスを構築して、このネームスペース内の Namenode との通信を維持します (ファイル システム データセットの BlockManager セクションの BPOfferService サブセクションを参照してください)。図 4-15 に示すように、BPOfferService の BPServiceActor クラスがネームスペースの Namenode と正常にハンドシェイクすると、DataNode.initBlockPool( を呼び出してネームスペースのブロック プールを初期化します。DataNode.initBlockPool0 メソッドは最終的に DataStorage を呼び出します。ブロックプールストレージの初期化を実行するためのrecoverTransitionRead()。

記事をご覧になっている方のお役に立てれば幸いです、注目、コメント、お気に入りを忘れずによろしくお願いします

おすすめ

転載: blog.csdn.net/u013412066/article/details/130469800