目次
この章ではDRBDの内部アルゴリズムと内部構造について、いくつかの背景情報を取り上げます。これは、DRBDの背景について関心のあるユーザが対象です。DRBD開発者が参考にできるほど深い内容には踏み込んでいません。開発者の方は「資料」に記載された文書やDRBDリソースソースコードを参照してください。
DRBDはレプリケートするデータに関するさまざまな情報を専用の領域に格納しています。このメタデータには次のようなものがあります。
このメタデータは内部または外部に格納されます。いずれの方法で格納するかは、リソースごとに設定できます。
内部メタデータを使用するようにリソースを設定すると、DRBDはメタデータを実際の本稼働データと同じ下位レベルの物理デバイスに格納します。デバイスの末尾の領域がメタデータを格納するための領域として確保されます。
メリット. メタデータは実際のデータと密接にリンクされているため、ハードディスクに障害が発生しても、管理者は特に何かする必要はありません。メタデータは実際のデータとともに失われ、ともに復元されます。
デメリット. RAIDセットではなく、下位レベルデバイスが唯一の物理ハードディスクの場合は、内部メタデータが原因で書き込みスループットが低下することがあります。アプリケーションによる書き込み要求の実行により、DRBDのメタデータの更新が引き起こされる場合があります。メタデータがハードディスクの同じ磁気ディスクに格納されている場合は、書き込み処理によって、ハードディスクの書き込み/読み取りヘッドが2回余分に動作することになります。
![]() | 注意 |
---|---|
すでにデータが書き込まれているディスク領域を下位デバイスに指定してDRBDでレプリケートする場合で、内部メタデータを使うには、DRBDのメタデータに必要な領域を必ず確保してください。 |
そうでない場合、DRBDリソースの作成時に、新しく作成されるメタデータによって下位レベルデバイスの末尾のデータが上書きされ、既存のファイルが破損します。以下のいずれかの方法でこれを避けることができます。
下位レベルデバイスをどの程度拡張するか、またはファイルシステムをどの程度縮小するかについては、「メタデータサイズの見積り」を参照してください。
外部メタデータは、本稼働データを格納するものとは異なる個別の専用ブロックデバイスに格納します。
メリット. 一部の書き込み処理では、外部メタデータを使用することにより、待ち時間をいくらか短縮できます。
デメリット. メタデータが実際の本稼働データに密接にリンクされません。つまり、ハードウェア障害により本稼働データだけが破損したか、DRBDメタデータは破損しなかった場合、手動による介入が必要です。生き残ったノードから切り替えるディスクに、手動でデータの完全同期を行う必要があります。
次の項目すべてに該当する場合には、外部メタデータ使用する以外の選択肢はありません。
デバイスのメタデータを格納する専用ブロックデバイスが必要とするサイズにについては「メタデータサイズの見積り」を参照してください。
![]() | 注記 |
---|---|
外部メタデータには最小で1MBのデバイスサイズが必要です。 |
DRBDでは世代識別子(GI)を使用してレプリケートされたデータの「世代」を識別します。
これはDRBDの内部メカニズムで、次のような目的で使用されます。
DRBDは次のような場合に、新しいデータ世代の開始としてマークを付けます。
つまり、リソースの接続状態が Connected になり、両方のノードのディスク状態が UpToDate になると、両方のノードの現在のデータ世代が同一になります。逆も同様です。現在の実装は、最下位ビットを使用してノードの役割(プライマリ/セカンダリ)をエンコードしていることに注意してください。よって、同じデータ世代でも、最下位ビットは異なることがあります。
新規のデータ世代は8バイトのUUID (Universally Unique Identifier)で識別されます。
DRBDでは、現在と履歴のデータ世代について4組の情報がローカルリソースメタデータに格納されます。
現在UUID. これは、ローカルノードからみた最新のデータ世代の世代識別子です。リソースが Connected になり完全に同期されると、両ノードの現在UUIDが同一になります。
Bitmap UUID. これは、オンディスク同期ビットマップにより変更が追跡されている世代のUUIDです。オンディスク同期ビットマップ自体については、切断モードの間のみこの識別子が意味を持ちます。リソースが Connected の場合は、このUUIDは常に空(ゼロ)です。
2つの履歴UUID. これらは現在の世代より前の2つのデータ世代識別子です。
まとめて、これら4つを世代識別子タプル、または略して「GIタプル」と呼びます。
ネットワーク障害や手動の介入によりノードが対向ノードとの接続を失うと、DRBDは次のようにローカル世代識別子を変更します。
再同期を開始すると、DRBDはローカルの世代識別子に対して次のような変更を行います。
ノード間の接続が確立すると、2つのノードは現在入手可能な世代識別子を交換し、それに従って処理を続行します。結果は次のようにいくつか考えられます。
両ノードの現在UUIDが空の場合. ローカルノードと対向ノードの両方で現在UUIDが空の状態です。新規に構成され、初回フル同期が完了していない場合は、通常この状態です。同期が開始していないため、手動で開始する必要があります。
1つのノードの現在UUIDが空の場合. 対向ノードの現在UUIDが空で、自身は空でない場合です。これは、ローカルノードを同期元とした初期フル同期が進行中であることを表します。初期フル同期の開始時に、ローカルノードのDRBDはディスク上の同期ビットマップのすべてのビットを1にして、ディスク全体が非同期だと マークします。その後ローカルノードを同期元とした同期が始まります。逆の場合(ローカルの現在UUIDが空で、対向ノードが空でない場合)は、DRBDは同様のステップをとります。ただし、ローカルノードが同期先になります。
現在UUIDが等しい場合. ローカルの現在UUIDと対向ノードの現在UUIDが空はなく、同じ値を持っている状態です。両ノードがともにセカンダリで、通信切断中にどのノードもプライマリにならなかったことを表します。この状態では同期は必要ありません。
ビットマップUUIDが対向ノードの現在UUIDと一致する場合. ローカルノードのビットマップUUIDが対向ノードの現在UUIDと一致し、対向ノードのビットマップUUIDが空の状態です。これは、ローカルノードがプライマリで動作している間にセカンダリノードが停止して再起動したときに生じる正常な状態です。これは、リモートノードは決してプライマリにならず、ずっと同じデータ世代にもとづいて動作していたことを意味します。この場合、ローカルノードを同期元とする通常のバックグラウンド再同期が開始します。逆に、ローカルノード自身のビットマップUUIDが空で、対向ノードのビットマップがローカルノードの現在UUIDと一致する状態の場合。これはローカルノードの再起動に伴う正常な状態です。この場合、ローカルノードを同期先とする通常のバックグラウンド再同期が開始します。
現在UUIDが対向ノードの履歴UUIDと一致する場合. ローカルノードの現在UUIDが対向ノードの履歴UUIDのうちの1つと一致する状態です。これは過去のある時点では同じデータを持っていたが、現在は対向ノードが最新のデータを持ち、しかし対向ノードのビットマップUUIDが古くなって使用できない状態です。通常の部分同期では不十分なため、ローカルノードを同期元とするフル同期が開始します。DRBDはデバイス全体を非同期状態とし、ローカルノードを同期先とするバックグラウンドでのフル再同期を始めます。逆の場合(ローカルノードの履歴UUIDのうち1つが対向ノードの現在UUIDと一致する)、DRBDは同様のステップを行いますが、ローカルノードが同期元となります。
ビットマップUUIDが一致し、現在UUIDが一致しない場合. ローカルノードの現在UUIDが対向ノードの現在UUIDと異なるが、ビットマップUUIDは一致する状態はスプリットブレインです。ただし、データ世代は同じ親を持っています。この場合、設定されていればDRBDがスプリットブレイン自動回復ストラテジが実行されます。設定されていない場合、DRBDはノード間の通信を切断し、手動でスプリットブレインが解決されるまで待機します。
現在UUIDもビットマップUUIDも一致しない場合. ローカルノードの現在UUIDが対向ノードの現在UUIDと異なり、ビットマップUUIDも一致しない状態です。これもスプリットブレインで、しかも過去に同一のデータ状態であったという保証もありません。したがって、自動回復ストラテジが構成されていても役に立ちません。DRBDはノード間通信を切断し、手動でスプリットブレインが解決されるまで待機します。
いずれのUUIDも一致しない場合. 最後は、DRBDが2つのノードのGIタプルの中に一致するものを1つも検出できない場合です。この場合は、関連のないデータと、切断に関する警告がログに記録されます。これは、相互にまったく関連のない2つのクラスタノードが誤って接続された場合に備えるDRBDの機能です。
書き込み操作中に、DRBDは書き込み操作をローカルの下位ブロックデバイスに転送するだけでなく、ネットワークを介して送信します。実用的な目的で、この2つの操作は同時に実行されます。タイミングがランダムな場合は、書込み操作が完了しても、ネットワークを介した転送がまだ始まっていないといった状況が発生する可能性があります。
この状況で、アクティブなノードに障害が発生してフェイルオーバが始まると、このデータブロックのノード間の同期は失われます。障害が発生したノードにはクラッシュ前にデータブロックが書き込まれていますが、レプリケーションはまだ完了していません。そのため、ノードが回復しても、このブロックは回復後の同期のデータセット中から取り除かれる必要があります。さもなくば、クラッシュしたノードは生き残ったノードに対して「先書き」状態となり、レプリケーションストレージの「オール・オア・ナッシング」の原則に違反してしまいます。これはDRBDだけでなく、実際、すべてのレプリケーションストレージの構成で問題になります。バージョン0.6以前のDRBDを含む他の多くのストレージソリューションでは、アクティブなノードに障害が発生した場合、回復後にそのノードを改めてフル同期する必要があります。
バージョン0.7以降のDRBDは、これとは異なるアプローチを採用しています。アクティビティログ(AL)は、メタデータ領域にに格納され、「最近」書き込まれたブロックを追跡します。この領域はホットエクステントと呼ばれます。
アクティブモードだったノードに一時的な障害が発生し、同期が行われる場合は、デバイス全体ではなくALでハイライトされたホットエクステントだけが同期されます。これによって、アクティブなノードがクラッシュしたときの同期時間を大幅に短縮できます。
アクティビティログの設定可能なパラメータに、アクティブエクステントの数があります。アクティブエクステントは4MiB単位でプライマリのクラッシュ後に再送されるデータ量に追加されます。このパラメータは、次の対立する2つの状況の折衷案としてご理解ください。
アクティブエクステントが多い場合. 大量のアクティビティログを記録すれば書き込みスループットが向上します。新しいエクステントがアクティブになるたびに、古いエクステントが非アクティブにリセットされます。この移行には、メタデータ領域への書き込み操作が必要です。アクティブエクステントの数が多い場合は、古いアクティブエクステントはめったにスワップアウトされないため、メタデータの書き込み操作が減少し、その結果パフォーマンスが向上します。
アクティブエクステントが少ない場合. アクティビティログが小さい場合は、アクティブなノードが障害から回復した後の同期時間が短くなります。
エクステントの数は所定の同期速度における適切な同期時間にもとづいて定義します。アクティブエクステントの数は次のようにして算出できます。
R はMB/秒単位の同期速度、tsync は秒単位のターゲットの同期時間です。E は求めるアクティブエクステントの数です。
スループット速度が90MiByte/秒のI/Oサブシステムがあり、同期速度が30MiByte/sに設定されているとします(R =30)。ターゲットの同期時間は4分(240秒)を維持する必要があります。(tsync =240):
正確な計算結果は1800ですが、DRBDのAL実装のハッシュ関数はエクステントの数が素数に設定されている場合に最適に動作します。したがって、ここでは1801を選択します。
クイック同期ビットマップはDRBDがリソースごとに使用する内部データ構造で、同期ブロック(両方のノードで同一)または非同期ブロックを追跡します。ビットマップはノード間通信が切断しているときのみ使われます。
クイック同期ビットマップでは、1ビットが4KiBチャンクのオンディスクデータを表します。ビットがクリアされていれば、対応するブロックが対向ノードと同期しています。つまり、切断以降、ブロックに書き込まれていないということです。逆に、ビットが設定されていればブロックが変更されているため、接続が再確立したらすぐに再同期を行う必要があります。
スタンドアロンノードでディスクにデータが書き込まれると、クイック同期ビットマップのへの書き込みも始まります。ディスクへの同期的なI/Oは負荷が大きいため、実際にはメモリ上のビットマップのビットが設定されます。アクティビティログ)が期限切れになってブロックがコールドになると、メモリ上のビットマップがディスクに書き込まれます。同様に、生き残ったスタンドアロンのノードでリソースが手動でシャットダウンされると、DRBDはすべてのビットマップをディスクにフラッシュします。
リモートノードが回復するか接続が再確立すると、DRBDは両方のノードのビットマップ情報を照合して、再同期が必要なすべてのデータ領域を決定します。同時に、DRBDは世代識別子を調べ、同期の方向を決定します。
同期元ノードが同期対象ブロックを対向ノードに送信し、同期先が変更を確認すると、ビットマップの同期ビットがクリアされます。別のネットワーク障害などで再同期が中断し、その後再開すると、中断した箇所から同期を続行します。 — 中断中にブロックが変更された場合、もちろんそのブロックが再同期データセットに追加されます。
![]() | 注記 |
---|---|
|
DRBDは、レプリケーションリンクが遮断したときに、対向ノードを切り離すメカニズムとして定義されたインタフェースを備えています。Heartbeatに同梱の
drbd-peer-outdater
ヘルパーはこのインタフェースのリファレンス実装です。ただし、独自のpeer
fencingヘルパープログラムも簡単に実装できます。
fencingヘルパーは次のすべてを満たす場合にのみ呼び出されます。
handlers
セクションで fence-peer
ハンドラが定義されている。
fencing
オプションで、resource-only
または resource-and-stonith
が設定されている。
fence-peer
ハンドラとして指定されたプログラムかスクリプトが呼び出されると、DRBD_RESOURCE
と DRBD_PEER
環境変数が利用できるようになります。これらの環境変数には、それぞれ、影響を受けるDRBDリソース名と対向ホストのホスト名が含まれています。
peer fencingヘルパープログラム(またはスクリプト)は、次のいずれかの終了コードを返します。
表16.1 fence-peer
ハンドラの終了コード
終了コード | 意味 |
---|---|
3 | 対向ノードのディスク状態がすでに Inconsistent になっている。 |
4 | 対向ノードのディスク状態が正常に Outdated に設定された(または最初から Outdated だった。) |
5 | 対向ノードへの接続に失敗。対向ノードに到達できなかった。 |
6 | 影響を受けるリソースがプライマリロールになっていたため、対向ノードを無効にできなかった。 |
7 | 対向ノードがクラスタから正常にフェンシングされた。影響を受けるリソースの |