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