Files
hse-2026/materials/08-scaling/seminar/kv/readme.md
T
2026-11-04 19:23:39 +03:00

4.5 KiB
Raw Blame History

Шардирование на примере простого key-value-хранилища

Этот пример показывает, как разделить данные между несколькими узлами. В стенде работают три простых key-value-хранилища: каждое принимает ключ и значение и сохраняет их в памяти. Перед ними находится прокси с единым API. Клиент обращается только к прокси, а тот определяет владельца ключа и пересылает запрос нужному хранилищу.

В основном режиме прокси вычисляет SHA-256(key) mod N и направляет запись и чтение владельцу ключа. В конце также кратко рассмотрен учебный режим репликации.

API

  • POST /put?key=<key> записывает значение из JSON-поля value.
  • GET /get?key=<key> возвращает значение или 404, если ключа нет на выбранном узле.
  • GET /state показывает содержимое всех хранилищ.

Запуск

Из корня репозитория:

cd materials/08-scaling/seminar/kv
docker compose up -d --build
docker compose ps

Прокси будет доступен на порту 5005. Хранилища будут доступны на портах 5001, 5002 и 5003.

Запись и чтение

Записать одно значение через прокси:

curl -sS -X POST 'http://localhost:5005/put?key=key-0' \
  -H 'Content-Type: application/json' \
  -d '{"value":"value-0"}'

Прочитать его:

curl -sS 'http://localhost:5005/get?key=key-0'

Записать N значений с ключами от key-0 до key-(N-1):

N=20

for ((i = 0; i < N; i++)); do
  curl -sS -X POST "http://localhost:5005/put?key=key-$i" \
    -H 'Content-Type: application/json' \
    -d "{\"value\":\"value-$i\"}"
  echo
done

Проверка распределения

Получить состояние всех узлов через прокси:

open 'http://localhost:5005/state'

Состояние отдельных хранилищ:

curl -sS 'http://localhost:5001/state'
curl -sS 'http://localhost:5002/state'

Для текущей конфигурации key-0 находится на третьем узле:

curl -i 'http://localhost:5003/get?key=key-0'  # 200
curl -i 'http://localhost:5002/get?key=key-0'  # 404

Изменение конфигурации

Состав узлов задаётся в proxy/compose_config.yml:

mode: sharding
nodes:
  - name: node1
    url: http://kv1:5000
  - name: node2
    url: http://kv2:5000
  - name: node3
    url: http://kv3:5000

Конфигурация подключена к контейнеру как файл только для чтения. После её изменения достаточно перезапустить прокси:

docker compose restart proxy

Хранилища при этом не перезапускаются, и данные в их памяти сохраняются.

Режим репликации

В режиме replication прокси записывает каждое значение во все хранилища. При чтении он опрашивает узлы по очереди и возвращает первый успешный ответ. В отличие от шардирования, данные не разделяются, а копируются.

Чтобы включить этот режим, изменить первую строку в proxy/compose_config.yml:

mode: replication

Затем перезапустить только прокси и повторить команды записи и чтения:

docker compose restart proxy
open 'http://localhost:5005/state'

После записи новый ключ должен появиться на всех трёх узлах. Это упрощённая учебная реализация: она не гарантирует согласованность при частичных записях и не обрабатывает отказы как промышленная система.