@nullpon / id:paulownia
コンシステント
ハッシュ法
consistent hashing
コンシステントハッシュ法
分散データベース/キャッシュの保存先を決定
するために開発されたハッシュテーブルのアル
ゴリズム
コンシステントハッシュ
のアルゴリズム
適当なハッシュ関数を用意
出力値が大小比較可能なハッシュ関数を用意
※ ここでは、入力値を0から127までの値に変換
する仮想のハッシュ関数 h で説明する
ノードのIDをハッシュ関数 h で変換
n1: h("n1") => 25
n2: h("n2") => 120
n3: h("n3") => 50
n4: h("n4") => 95
リング状に配置
データのIDをハッシュ関数 h で変換
a1: h("a1") => 64
a2: h("a2") => 115
a3: h("a3") => 75
a4: h("a4") => 8
a5: h("a5") => 100
a6: h("a6") => 90
a7: h("a7") => 45
a8: h("a8") => 15
リング状に配置
データの割り当て先ノードは以下の順に決定
データIDのハッシュ値と同じノード
データIDより大きいハッシュ値を持つノード
のなかで、ハッシュ値が最小のノード
ハッシュ値が最小のノード
ノードの追加と削除
ノードの追加
n4のデータの一部がn5へ移動
ノードの削除
n1のデータがn3へ移動
移動するデータ数の平均値
データ数/ノード数
仮想ノード
仮想ノードなしでは、負荷分散が不完全
偏ったリング
データが特定のノードに偏り
負荷分散にならない
ノードがダウン
落ちたノードの全データが一つ先のノードへ
移動
一つ先のノードの負荷が2倍
特定のノードに負荷が集中
ノードを追加
1つ先のノードからデータが移動
1つ先のノードの負荷しか減らない
負荷対策にならない
そこで仮想ノード
n1: h("n1"+0) => 25
n1: h("n1"+1) => 100
n1: h("n1"+2) => 90
n2: h("n2"+0) => 120
n2: h("n2"+1) => 45
n2: h("n2"+2) => 13
…
ハッシュ関数 h でノードID+αを変換
リング状に配置
ノード数が増えれば均等に分散する確率が高くなる
ノード4が追加された場合
複数のノードから均等にデータが
移動してくる可能性が高い
ノード1がダウンした場合
ノード1のデータが複数のノードへ
均等に分散することが期待できる
メリット・デメリット
メリット
データの割り当て先を自動で決定可能
データをクラスタに均等に分散できる
ノードが落ちた時、自動で再割り当て
再割り当てのコストが小さい
デメリット
全てのノードが現在のクラスタの状態を正確に
知ってなければならない。
クラスタ状態の共有コストがかかる
まとめ
コンシステントハッシュを用いると
プロセスが1つ2つ程度落ちても問題のない
クラスタを構成できる
負荷分散についてエンジニアが手を動かす
必要がない
大規模な分散環境でも運用が楽
(かもしれない)

Consistent hash