Какую проблему решает консистентное хеширование и как оно работает?

Ответ

Консистентное хеширование решает проблему минимизации перераспределения данных при добавлении или удалении узлов (серверов) в распределённой системе (например, в кластере кэша или базе данных).

Проблема без него (наивный подход):
При использовании простого хеширования вида hash(key) % N, где N — количество серверов, любое изменение N (добавление или удаление сервера) приводит к изменению результата для большинства ключей. Это вызывает массовое перемещение данных по всей системе, создавая огромную нагрузку.

Как работает консистентное хеширование:

  1. Хеш-кольцо: Вместо линейного распределения используется абстрактное кольцо (например, от 0 до 2^32 - 1).
  2. Размещение узлов: Каждый узел (сервер) хешируется и помещается в несколько точек на этом кольце (виртуальные ноды для более равномерного распределения).
  3. Размещение данных: Ключ данных также хешируется, и данные сохраняются на первом узле, который встречается на кольце при движении по часовой стрелке от точки хеша ключа.

Результат: При добавлении или удалении узла перераспределению подлежат только ключи, находящиеся в его зоне ответственности (в среднем K/N ключей), а не все данные в кластере.

Пример реализации на Go:

package main

import (
    "fmt"
    "hash/crc32"
    "sort"
)

// Ring представляет хеш-кольцо
type Ring struct {
    nodes   []uint32       // Отсортированные хеши узлов
    nodeMap map[uint32]string // Маппинг хеша на имя узла
}

// Get находит узел для заданного ключа
func (r *Ring) Get(key string) string {
    hash := crc32.ChecksumIEEE([]byte(key))

    // sort.Search находит первый узел, чей хеш >= хешу ключа
    idx := sort.Search(len(r.nodes), func(i int) bool {
        return r.nodes[i] >= hash
    })

    // Если мы вышли за пределы, возвращаемся к началу кольца
    if idx == len(r.nodes) {
        idx = 0
    }

    return r.nodeMap[r.nodes[idx]]
}

Где используется: Распределенные базы данных (Cassandra, Riak), системы кэширования (Redis Cluster, Memcached), балансировщики нагрузки и CDN.