一貫性のあるハッシュアルゴリズムとJava実装

一貫性のあるハッシュアルゴリズムとJava実装

コンシステント ハッシュ アルゴリズムは、1997 年にマサチューセッツ工科大学によって提案された分散ハッシュ (DHT) 実装アルゴリズムです。その設計目標は、インターネット上のホット スポット問題を解決することです。その本来の意図は CARP と非常に似ています。一貫性ハッシュは、CARP で使用される単純なハッシュ アルゴリズムによって発生する問題を修正し、分散ハッシュ (DHT) を P2P 環境で実際に適用できるようにします。

一貫性のあるハッシュ アルゴリズムでは、動的に変化するキャッシュ環境におけるハッシュ アルゴリズムの品質を決定するための 4 つの定義が提案されています。

1. バランス: バランスとは、ハッシュ結果を可能な限りすべてのバッファに分散し、すべてのバッファスペースを活用できることを意味します。多くのハッシュ アルゴリズムがこの条件を満たすことができます。

2. 単調性: 単調性とは、ハッシュによって対応するバッファに何らかのコンテンツが割り当てられている場合に、新しいバッファがシステムに追加されることを意味します。ハッシュ結果により、元の割り当てられたコンテンツが元のバッファまたは新しいバッファにマップできるが、古いバッファ セット内の他のバッファにはマップできないことが保証されます。

3. 拡散: 分散環境では、端末はすべてのバッファではなく、その一部のみを認識する場合があります。端末がハッシュ処理を通じてコン​​テンツをバッファにマッピングする場合、異なる端末は異なるバッファ範囲を認識する可能性があり、ハッシュ結果に一貫性がなくなる可能性があります。最終的には、同じコンテンツが異なる端末によって異なるバッファにマッピングされることになります。この状況は、同じコンテンツが異なるバッファーに保存され、システム ストレージの効率が低下するため、明らかに回避する必要があります。分散は、上記が発生する度合いとして定義されます。優れたハッシュ アルゴリズムは、矛盾を可能な限り回避し、つまり分散を可能な限り削減できる必要があります。

4. 負荷: 負荷の問題は、実際には分散の問題を別の観点から見ていることになります。異なる端末では同じコンテンツが異なるバッファにマップされる可能性があるため、特定のバッファは異なるユーザーによって異なるコンテンツにマップされる可能性があります。分散と同様に、この状況は回避する必要があるため、優れたハッシュ アルゴリズムでは、バッファ負荷を可能な限り削減できる必要があります。

分散クラスターでは、マシンの追加や削除、またはマシンの障害発生後にクラスターから自動的に離脱することが、分散クラスター管理の最も基本的な機能です。一般的に使用される hash(object)%N アルゴリズムを使用すると、マシンが追加または削除された後に元のデータの多くが見つからなくなり、単調性原理に重大な違反が発生します。次に、主にコンシステント・ハッシュ・アルゴリズムの設計方法について説明します。

リングハッシュスペース

一般的に使用されるハッシュ アルゴリズムによれば、対応するキーは 2^32 個のバケットを持つ空間、つまり 0 から (2^32)-1 までのデジタル空間にハッシュされます。ここで、これらの数字を端から端までつなげて、閉じた円として想像してみましょう。下記の通り

データは特定のハッシュアルゴリズムによって処理され、リングにマッピングされます

ここで、特定のハッシュ関数を使用して、4 つのオブジェクト object1、object2、object3、object4 の対応するキー値を計算し、それらをハッシュ リングにハッシュします。以下のように表示されます。

ハッシュ(オブジェクト1) = キー1;

ハッシュ(オブジェクト2) = キー2;

ハッシュ(オブジェクト3) = キー3;

ハッシュ(オブジェクト4) = キー4;

ハッシュアルゴリズムを使用してマシンをリングにマッピングする

一貫性のあるハッシュ アルゴリズムを使用する分散クラスターに新しいマシンを追加する場合、原則として、オブジェクト ストレージと同じハッシュ アルゴリズムを使用してマシンをリングにマップし (通常、マシンのハッシュ計算では、マシンの IP またはマシンの一意のエイリアスを入力値として使用します)、時計回りに計算して、最も近いマシンにすべてのオブジェクトを保存します。

NODE1、NODE2、NODE3 の 3 つのマシンがあるとします。対応する KEY 値はハッシュ アルゴリズムを通じて取得され、リングにマッピングされます。概略図は次のとおりです。

ハッシュ(NODE1) = KEY1;

ハッシュ(NODE2) = KEY2;

ハッシュ(NODE3) = KEY3;

上の図から、オブジェクトとマシンが同じハッシュ空間にあることがわかります。時計回りに、object1 は NODE1 に格納され、object3 は NODE2 に格納され、object2 と object4 は NODE3 に格納されます。このような展開環境では、ハッシュリングは変化しません。そのため、オブジェクトのハッシュ値を計算することで、対応するマシンをすばやく見つけることができ、オブジェクトの実際の保存場所を見つけることができます。

マシンの削除と追加

通常のハッシュ剰余アルゴリズムの最も不適切な点は、マシンが追加または削除された後に多数のオブジェクト ストレージの場所が無効になり、単調性要件に大きく違反することです。一貫性ハッシュアルゴリズムがどのように処理されるかを分析してみましょう。

1. ノード(マシン)の削除

上記の分布を例にとると、NODE2 に障害が発生して削除された場合、時計回りの移行方法に従って object3 が NODE3 に移行されます。このように、object3 のマッピング位置のみが変更され、他のオブジェクトは変更されません。以下のように表示されます。

2. ノード(マシン)の追加

新しいノード NODE4 がクラスターに追加されると、次に示すように、対応するハッシュ アルゴリズムを通じて KEY4 が取得され、リングにマッピングされます。

時計回りの移行ルールに従って、object2 は NODE4 に移行され、他のオブジェクトは元の保存場所を保持します。一貫性のあるハッシュ アルゴリズムは、ノードの追加と削除の分析を通じて、単調性を維持しながらデータ移行を最小限に抑えることができます。このようなアルゴリズムは分散クラスターに非常に適しており、大量のデータ移行を回避し、サーバーの負荷を軽減します。

バランス

上記のグラフ分析によると、コンシステント ハッシュ アルゴリズムは、一般的なハッシュ アルゴリズムの分散化だけでなく、単調性と負荷分散の特性も満たしていますが、まだバランスが欠けているため、これが広く使用されている理由とは見なされません。以下では、コンシステント・ハッシュ・アルゴリズムがバランス要件をどのように満たすかを分析します。ハッシュアルゴリズムはバランスを保証するものではありません。例えば、NODE1とNODE3のみが展開されている上記ケース(NODE2が削除された図)では、object1はNODE1に格納され、object2、object3、object4はすべてNODE3に格納されるため、非常にアンバランスな状態になります。コンシステント ハッシュ アルゴリズムでは、可能な限りバランスを実現するために仮想ノードが導入されます。

——「仮想ノード」とは、ハッシュ空間における実ノード(マシン)のレプリカです。1 つの実ノード(マシン)は複数の「仮想ノード」に対応しており、この対応数は「レプリカ数」とも呼ばれます。「仮想ノード」はハッシュ値とともにハッシュ空間に配置されます。

上記の NODE1 と NODE3 のみがデプロイされている場合 (NODE2 が削除された図) を例に挙げます。 以前のマシン上のオブジェクトの分布は非常に不均一でした。 ここで、2 つのコピー (コピーの数) を例に挙げてみましょう。 このように、ハッシュ リング全体に 4 つの仮想ノードがあります。 *** オブジェクト マッピングの関係図は次のとおりです。

上図によれば、オブジェクトのマッピング関係は、object1->NODE1-1、object2->NODE1-2、object3->NODE3-2、object4->NODE3-1 となります。仮想ノードを導入することで、オブジェクトの分散がよりバランスよくなります。では、実際のオブジェクト クエリは実際にはどのように機能するのでしょうか。オブジェクトをハッシュから仮想ノード、そして実際のノードに変換する様子を次の図に示します。

「仮想ノード」のハッシュ計算は、対応するノードの IP アドレスに数値サフィックスを追加することによって実行できます。たとえば、NODE1 の IP アドレスが 192.168.1.100 であるとします。 「仮想ノード」を導入する前に、キャッシュ A のハッシュ値を計算します。

ハッシュ("192.168.1.100");

「仮想ノード」を導入した後、「仮想ノード」NODE1-1とNODE1-2のハッシュ値を計算します。

ハッシュ("192.168.1.100#1"); // NODE1-1

ハッシュ("192.168.1.100#2"); // NODE1-2

Java実装:

  1. public class Shard<S> { // クラス S は、名前パスワード、IP、ポートなどのマシン ノードの情報をカプセル化します。
  2. private TreeMap<Long, S> nodes; // 仮想ノード
  3. private List<S> shards; // 実際のマシンノード
  4. private final int NODE_NUM = 100; // 各マシンノードに関連付けられた仮想ノードの数
  5. パブリックシャード(リスト<S> シャード) {
  6. 素晴らしい();
  7. this.shards = 破片;
  8. 初期化();
  9. }
  10. private void init() { // 一貫性のあるハッシュリングを初期化する
  11. ノード = 新しい TreeMap<Long, S>();
  12. for ( int i = 0; i != shards.size ( ); ++i) { // 各実マシンノードは仮想ノードに関連付ける必要があります
  13. 最終的なS shardInfo = shards.get(i);
  14. ( int n = 0; n < NODE_NUM; n++)の場合
  15. // 実マシンノードはNODE_NUM仮想ノードに関連付けられます
  16. nodes.put(hash( "SHARD-" + i + "-NODE-" + n), shardInfo);
  17. }
  18. }
  19. パブリックS getShardInfo(文字列キー) {
  20. SortedMap<Long, S> tail = nodes.tailMap(hash( key )); // リングの時計回り方向に沿って仮想ノードを見つける
  21. テールサイズ()== 0)の場合{
  22. ノードを返します。get(ノード.firstKey());
  23. }
  24. return tail.get(tail.firstKey()); // 仮想ノードに対応する実機ノードの情報を返します
  25. }
  26. /**
  27. * MurMurHash アルゴリズムは、高性能な非暗号化 HASH アルゴリズムです。
  28. * 従来のCRC32、MD5、SHA-1と比較すると(これら2つのアルゴリズムは暗号化されたHASHアルゴリズムであり、複雑さが非常に高く、パフォーマンスの低下は避けられません)
  29. * HASH アルゴリズムははるかに高速であり、このアルゴリズムの衝突率は非常に低いと言われています。
  30. * http://murmurhash.googlepages.com/
  31. */
  32. プライベートLongハッシュ(文字列キー) {
  33. ByteBuffer buf = ByteBuffer.wrap(キー.getBytes() );
  34. 整数シード = 0x1234ABCD;
  35. バイト順序 byteOrder = buf.order ();
  36. buf.order (ByteOrder.LITTLE_ENDIAN);
  37. 長いm = 0xc6a4a7935bd1e995L;
  38. 整数r = 47;
  39. 長い h = シード ^ (buf.remaining() * m);
  40. 長いk;
  41. (buf.remaining() >= 8) の間 {
  42. buf の戻り値:
  43. k*=m;
  44. k ^= k >>> r;
  45. k*=m;
  46. h^=k;
  47. h*=m;
  48. }
  49. buf.remaining() > 0 の場合 {
  50. ByteBuffer 終了 = ByteBuffer.allocate(8) .order (
  51. バイト順序.LITTLE_ENDIAN);
  52. //ビッグエンディアン版の場合はまずこれを実行します:
  53. // 終了位置(8-buf.remaining());
  54. 終了。buf に巻き戻し() を入れる。
  55. h ^= 終了.getLong();
  56. h*=m;
  57. }
  58. h ^= h >>> r;
  59. h*=m;
  60. h ^= h >>> r;
  61. buf.order (バイト順序);
  62. hを返します
  63. }
  64. }

[この記事は51CTOコラムニスト「王森鋒」によるオリジナル記事です。転載の際は出典を明記してください。]

<<:  TensorFlow を通じてディープラーニング アルゴリズムを実装し、企業の実務に適用する方法

>>:  オタクのためのオープンソースドローンプロジェクト4つ

ブログ    
ブログ    
ブログ    
ブログ    

推薦する

機械学習のヒント: モデルパラメータとハイパーパラメータの違いをご存知ですか?

[[199395]]導入機械学習におけるモデルパラメータとモデルハイパーパラメータは機能やソースが...

Aiti Tribe Clinic 第 6 回: 機械学習は緊急事態をどのように判断するのか?

[51CTO.com からのオリジナル記事]活動の説明: Aiti Tribe は、コア開発者に詳...

...

スウェット物流からスマート物流へ、物流業界はよりスマートになっている

2020年は異例の年です。新型コロナウイルスの世界的な蔓延は人々の生活や仕事に多くの不便をもたらし、...

自動運転車は交通事故のほとんどをなくすことはできないかもしれない

統計によると、交通事故のほぼ主な原因は運転者の過失です。そのため、自動化は長い間、セキュリティにおけ...

...

小売業界におけるRPA活用事例11選

世界各国がインダストリー4.0の時代を迎える中、多くの業界団体がプロセス自動化の重要性を認識し始め、...

...

...

ICDM の選択: データ マイニングの代表的なアルゴリズム トップ 10

2006 年 12 月、国際的に有名な学術組織である IEEE 国際データマイニング会議 (ICD...

「段階的に考える」だけでは不十分です。モデルを「より多くのステップで考える」ようにすれば、より有用になります。

今日では、大規模言語モデル (LLM) とその高度なヒント戦略の出現により、特に古典的な NLP タ...

自然言語処理必読本: 理論と実践のバランスが取れた 5 冊の本

この記事は、公開アカウント「Reading the Core」(ID: AI_Discovery)か...

Python に基づく簡単な自然言語処理の練習

Python によるシンプルな自然言語処理この記事は、Python をベースにした簡単な自然言語処理...

Sparkに代わると期待されるリアルタイム機械学習フレームワークRay

新しいプロジェクトは、Python で記述された機械学習アプリケーションをサポートするために使用でき...