6

私はすでに、このトピックに関する多くのドキュメントをレビューしましたが、明確でないことがあります。たとえば、ビット トレント ドキュメント ( http://www.bittorrent.org/beps/bep_0005.html ) には次のように記載されています。

ルーティング テーブルは、それぞれがスペースの一部をカバーする「バケット」に分割されます。空のテーブルには、最小 = 0、最大 = 2^160 の ID スペース範囲を持つ 1 つのバケットがあります。ID「N」を持つノードがテーブルに挿入されると、最小 <= N < 最大のバケット内に配置されます。空のテーブルにはバケットが 1 つしかないため、ノードはその中に収まる必要があります。各バケットは、「満杯」になる前に K ノード (現在は 8 つ) しか保持できません。バケットが既知の正常なノードでいっぱいになると、独自のノード ID がバケットの範囲内に収まらない限り、それ以上ノードを追加できません。その場合、バケットは、それぞれが古いバケットの半分の範囲を持つ 2 つの新しいバケットに置き換えられ、古いバケットのノードは 2 つの新しいバケットに分散されます。バケットが 1 つしかない新しいテーブルの場合、

ノードIDのビットプレフィックスに従ってバケットが配置されるkademliaルーティングテーブルに関する他のドキュメントとは少し異なりますが、もう1つ紛らわしいことがあります。「ノードの検索」リクエストに応答するとき、XOR 操作を使用して、リクエストされたノードに最も近い 8 つのノードを見つける必要があります。一部の実装では、XOR 操作を実行するルーティング テーブル内の各アイテムを調べて、最も近い 8 つのアイテムを見つけました。私にもCPUの浪費のようです。

すべてがすでにバケツに入っています。ビット トレント ドキュメント システムによって提案されたものを使用したとしても、バケットを列挙してその最小数と最大数をチェックするだけで、要求されたノード ID を含む可能性のあるバケットをより迅速に見つけることができます。次に、潜在的にそのバケットにクローズノードが含まれている必要がありますが、それらはXORに最も近いノードではなく、値に最も近いノードです(私が理解しているように)。これは多少異なりますが、多少似ています。

0 から 99 までの数字を使用して簡単なテストを実行しました。ここでは、最も近い 8 つの XOR 数字を見つけたいと思っていました。ここで、バケットについて考えてみると、バケット内のすべてのノード ID がマイナーな例外に最も近い可能性があると思います。したがって、たとえば、このバケットを左から 1 つと右から 1 つ取得し、XOR 最も近いノード ID を検索すると、探しているものが見つかります。ルーティングですべてのノードを通過する意味はありません。テーブル。

私は正しいですか、それとも何か不足していますか?

4

1 に答える 1

5

ノードIDのビットプレフィックスに従ってバケットが配置されるkademliaルーティングテーブルに関する他のドキュメントとは少し異なりますが、もう1つ紛らわしいことがあります。

bittorrent の仕様では、 kademlia の論文で説明されているものに近似するだけのルーティング テーブルの実装が説明されています。実装は簡単ですが、いくつかの欠点があります。

したがって、たとえば、このバケットを左から 1 つと右から 1 つ取得し、XOR 最も近いノード ID を検索すると、探しているものが見つかります。ルーティングですべてのノードを通過する意味はありません。テーブル。

完全なツリー状のルーティング テーブル実装と単純化された BEP5 バリアントの両方で、各バケットは、バケットがカバーするプレフィックス ビットとマスク ビットで構成されるCIDR のようなプレフィックス(この SO の回答を参照) を持つと考えることができます。カウント。

BEP5 バリアントでは、各バケットのプレフィックスは、配列インデックスとノード自体の ID から単純に派生します。ツリー状のテーブルでは、バケットの分割/マージ操作のために、バケットはプレフィックスを追跡する必要があります。

これらのプレフィックスを使用して、ターゲット キーをカバーするバケットを見つけることができます。

問題は、バケットがいっぱいである必要はないということです。送信したい場合、1 つのバケットでは不十分な応答で 20 ノードとしましょう。

そのため、複数のバケットにアクセスするには、ルーティング テーブル (独自のノード ID に基づいて、または自然距離に基づいて並べ替え)をターゲット キーに相対的な昇順 (XOR) でトラバースする必要があります。

XOR 距離メトリックは各ビットキャリー (XOR == キャリーレス加算) で折り畳まれるため、どのルーティング テーブル レイアウトにも適切にマップされません。つまり、最も近いバケットにアクセスするだけでは不十分です。

これは、ツリーのようなルーティング テーブルから特定のターゲット キーに最も近い N 個のノードを見つけるための実装です。

通常のノードの場合、最大で数十個のバケットしか含まれておらず、DHT ノードには多くのトラフィックが表示されないため、多くの人がルーティング テーブル全体を単純に反復処理しているため、この操作を 1 秒あたり数回実行するだけで済みます。これを高密度でキャッシュに適したデータ構造に実装すると、ライオンの分け前は実際にはメモリ トラフィックであり、いくつかの XOR と比較を行う CPU 命令ではない可能性があります。

つまり、テーブル全体のスキャンは簡単に実装できます。


各バケットに次のビット プレフィックスを持つルーティング テーブルがあるとします。文字は便利な名前として機能します)。

A 000... 
B 00100... 
C 0010100... 
D 0010101000... 
E 0010101001...
F 001010101... 
G 00101011... 
H 001011... 
I 0011... 
J 01... 
K 1... 

ここで、このターゲット キーを探しているとしましょう。

T = 0010011010111111001111100101011000001010010100001100100010011100000000100100000111001101100110110110101100010100111010111001101111110101001001001000100000001001

また、バケットが完全にいっぱいではないか、1 つのバケットに収まるよりも多くのエントリが必要なため、目的の量を取得するには複数のバケットにアクセスする必要があります。

これで、最初にアクセスするバケットは明らかです。これはB、そのプレフィックスがターゲット キーをカバーしているためです。

Bのプレフィックスは 5 ビット長であるため、そのバケット内のすべてのエントリは までの XOR 距離を持ちTます00000???????...。5 つのプレフィックス ビットが共有されます。

Bは に最も近いバケットです。Tつまり、相対距離 より近くにルーティング テーブル エントリが存在することはありません00000...。逆に言えば、 の外側にあるエントリの最小距離Bは です00001...。つまり、次に近いバケットが をカバーする必要がありますT xor 00001... -> 00101110101111110[...]

これをカバーするバケツはH.

H隣接していないB

最終的に、6 つのバケットにアクセスする必要があると仮定すると、順序は次のようになります。

00100...      -> B
001011...     -> H
001010101...  -> F
0010101000... -> D
0010101001... -> E
00101011...   -> G

これはかなり混沌としているようです。しかし、訪問した各バケットのプレフィックスからターゲット キーまでの距離をプロットすると、もう少し明白になります。

00000...
000010...
000011000...
0000110010...
0000110011...
00001101...

したがって、アルゴリズムは次のようになります。

  1. ターゲット キーをカバーする最初のバケットを見つける
  2. バケットのプレフィックスとターゲット キーの XOR (ゼロ マスクの後続ビット)
  3. そのプレフィックスの最下位ビットで距離を増やします
  4. XOR 増分距離とターゲット キー
  5. XORed キーをカバーする次のバケットを見つける
  6. 2に行く

TL;DR: 「左に 1 つのバケツ、右に 1 つのバケツを見てください」では十分ではありません。正しいアルゴリズムはかなり複雑で、テーブル全体の線形スキャンの方が実装が簡単です。

于 2015-06-04T22:38:45.470 に答える