4.5 KiB
Шардирование на примере простого 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'
После записи новый ключ должен появиться на всех трёх узлах. Это упрощённая учебная реализация: она не гарантирует согласованность при частичных записях и не обрабатывает отказы как промышленная система.