Overview
コンシステントハッシュ(Consistent Hashing)とは何でしょうか? これを知る前に、まずhashing(ハッシュ化)という言葉は「刻んで混ぜる」と理解できます。Hash Mapはインデックスにデータをマッピングしたデータ構造です。O(1)であり最も効率的だと言えます。通常はキーと値のペアで保存するのが一般的です。
ハッシュについてはこれくらいにして、分散ハッシュについて話してみましょう。
分散ハッシュ
以下のハッシュテーブルがあると仮定してみましょう。今、私たちはこのデータを分散データストアに保存しようとしています。
| KEY | HASH | HASH mod 3 |
|---|---|---|
| “john” | 1633428562 | 2 |
| “bill” | 7594634739 | 0 |
| “jane” | 5000799124 | 1 |
| “steve” | 9787173343 | 0 |
| “kate” | 3421657995 | 2 |
3台のサーバーに分けて保存すると、以下のように整理されます。 それぞれ A:0, B:1, C:2 のインデックスを持ちます。
| A | B | C |
|---|---|---|
| “bill” | “jane” | “john” |
| “steve” | “kate” |
このようにうまく使っている状況で、突然機器が1台故障したと考えてみましょう。サーバーCがダウンしたと仮定すると、再び以下のようにハッシュテーブルとサーバーにデータが割り当てられることになります。
| KEY | HASH | HASH mod 2 |
|---|---|---|
| “john” | 1633428562 | 0 |
| “bill” | 7594634739 | 1 |
| “jane” | 5000799124 | 0 |
| “steve” | 9787173343 | 1 |
| “kate” | 3421657995 | 1 |
これで A:0, B:1 の2台のストレージにデータが以下のように保存されます。
| A | B |
|---|---|
| “john” | “bill” |
| “jane” | “steve” |
| “kate” |
このようになると、Cに存在していたすべてのキーの位置が変更されることになり、この時、元データからの再ハッシュ(re-hashing)作業が必要となります。これはオリジンサーバーに負荷を与えることになります。そしてその間、クライアントがリクエストしたデータは失われてしまいます。
これを解決するために登場したハッシュ手法が、まさにコンシステントハッシュ(Consistent Hashing)です。
Consistent Hashing

上の画像が今回話す全てです。 上の画像に従ってハッシュ化を行うと考えてみましょう。
| KEY | HASH | ANGLE (DEG) |
|---|---|---|
| “john” | 1633428562 | 58.7 |
| “C” | 2269549488 | 81.7 |
| “kate” | 3421657995 | 123.1 |
| “jane” | 5000799124 | 180 |
| “A” | 5572014557 | 200.5 |
| “bill” | 7594634739 | 273.4 |
| “B” | 8077113361 | 290.7 |
| “steve” | 787173343 | 352.3 |
サーバーもハッシュテーブルに一緒に配置します。
ここで各キーが位置するサーバーを見つけるルールは一つです。
反時計回りに回る時、最も近いサーバーがそのキーが位置する保存場所です。
先ほど述べた基準でキーが保存されている場所を整理すると以下のようになります。
| KEY | HASH | ANGLE (DEG) | LABEL | SERVER |
|---|---|---|---|---|
| “john” | 1632929716 | 58.7 | “C” | C |
| “kate” | 3421831276 | 123.1 | “A” | A |
| “jane” | 5000648311 | 180 | “A” | A |
| “bill” | 7594873884 | 273.4 | “B” | B |
| “steve” | 9786437450 | 352.3 | “C” | C |
では、一体この手法のメリットは何でしょうか?
想像してみましょう。もしCの機器が削除されたとします。既存の手法ではすべてのキーが再ハッシュされなければなりませんでした。
まさにここで、この手法を通じて私たちはCの機器に割り当てられているキーだけ再ハッシュが必要であることを知ることができます。
A、Bのサーバーを見ているキーは、すでに最も近い位置A、Bを見ているためです。Cがなくなってもそれらのキーに変更事項はありません。Cサーバーに割り当てられたキーだけ再ハッシュが必要です。
逆に機器が追加されても K/N (キーの数 / 機器数)だけの再ハッシュが必要なだけで、すべてのキーに対して再ハッシュが必要なわけではありません。
例えばキーが3つで、機器が2つだった時。この間に機器が1つ入ると考えると、機器にキーが均等に入るように設計したと仮定すれば、3/3 = 1つのキーに対して再ハッシュが起こり得て、これは結局、機器1つにつき1つのキーが保存されるバランスの取れた姿を見せることができます。
Consistent Hashing は問題を抱えています。それはキーの偏りです。これをどうすれば緩和できるでしょうか?
Ketama Consistent Hashing

まず最も簡単な方法は、サーバーを複数のトークンに分割して Consistent Hashing Circle に配置することです。 これがまさに Ketama Consistent Hashing 手法です。AサーバーをA0-A10まで分散させ、キーの配置が極力均一になるようにします。
考察
- 結局、再ハッシュ(rehashing)は避けられない問題です。最小限の再ハッシュで済むように設計し、構築することが分散処理の要求事項だと考えられます。