forked from course/hse-2026
Add week 8 materials
This commit is contained in:
1 parent
a987b82834
commit
0bf71ed374
38 files changed
+2908
No files matched your search
@@ -0,0 +1,124 @@
|
||||
# Шардирование на примере простого key-value-хранилища
|
||||
|
||||
Этот пример показывает, как разделить данные между несколькими узлами. В стенде работают три простых
|
||||
key-value-хранилища: каждое принимает ключ и значение и сохраняет их в памяти. Перед ними находится прокси
|
||||
с единым API. Клиент обращается только к прокси, а тот определяет владельца ключа и пересылает запрос
|
||||
нужному хранилищу.
|
||||
|
||||
В основном режиме прокси вычисляет `SHA-256(key) mod N` и направляет запись и чтение владельцу ключа.
|
||||
В конце также кратко рассмотрен учебный режим репликации.
|
||||
|
||||
## API
|
||||
|
||||
- `POST /put?key=<key>` записывает значение из JSON-поля `value`.
|
||||
- `GET /get?key=<key>` возвращает значение или `404`, если ключа нет на выбранном узле.
|
||||
- `GET /state` показывает содержимое всех хранилищ.
|
||||
|
||||
## Запуск
|
||||
|
||||
Из корня репозитория:
|
||||
|
||||
```bash
|
||||
cd materials/08-scaling/seminar/kv
|
||||
docker compose up -d --build
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
Прокси будет доступен на порту 5005. Хранилища будут доступны на портах 5001, 5002 и 5003.
|
||||
|
||||
## Запись и чтение
|
||||
|
||||
Записать одно значение через прокси:
|
||||
|
||||
```bash
|
||||
curl -sS -X POST 'http://localhost:5005/put?key=key-0' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"value":"value-0"}'
|
||||
```
|
||||
|
||||
Прочитать его:
|
||||
|
||||
```bash
|
||||
curl -sS 'http://localhost:5005/get?key=key-0'
|
||||
```
|
||||
|
||||
Записать `N` значений с ключами от `key-0` до `key-(N-1)`:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
## Проверка распределения
|
||||
|
||||
Получить состояние всех узлов через прокси:
|
||||
|
||||
```bash
|
||||
open 'http://localhost:5005/state'
|
||||
```
|
||||
|
||||
Состояние отдельных хранилищ:
|
||||
|
||||
```bash
|
||||
curl -sS 'http://localhost:5001/state'
|
||||
curl -sS 'http://localhost:5002/state'
|
||||
```
|
||||
|
||||
Для текущей конфигурации `key-0` находится на третьем узле:
|
||||
|
||||
```bash
|
||||
curl -i 'http://localhost:5003/get?key=key-0' # 200
|
||||
curl -i 'http://localhost:5002/get?key=key-0' # 404
|
||||
```
|
||||
|
||||
## Изменение конфигурации
|
||||
|
||||
Состав узлов задаётся в `proxy/compose_config.yml`:
|
||||
|
||||
```yaml
|
||||
mode: sharding
|
||||
nodes:
|
||||
- name: node1
|
||||
url: http://kv1:5000
|
||||
- name: node2
|
||||
url: http://kv2:5000
|
||||
- name: node3
|
||||
url: http://kv3:5000
|
||||
```
|
||||
|
||||
Конфигурация подключена к контейнеру как файл только для чтения. После её изменения достаточно
|
||||
перезапустить прокси:
|
||||
|
||||
```bash
|
||||
docker compose restart proxy
|
||||
```
|
||||
|
||||
Хранилища при этом не перезапускаются, и данные в их памяти сохраняются.
|
||||
|
||||
## Режим репликации
|
||||
|
||||
В режиме `replication` прокси записывает каждое значение во все хранилища. При чтении он опрашивает
|
||||
узлы по очереди и возвращает первый успешный ответ. В отличие от шардирования, данные не разделяются,
|
||||
а копируются.
|
||||
|
||||
Чтобы включить этот режим, изменить первую строку в `proxy/compose_config.yml`:
|
||||
|
||||
```yaml
|
||||
mode: replication
|
||||
```
|
||||
|
||||
Затем перезапустить только прокси и повторить команды записи и чтения:
|
||||
|
||||
```bash
|
||||
docker compose restart proxy
|
||||
open 'http://localhost:5005/state'
|
||||
```
|
||||
|
||||
После записи новый ключ должен появиться на всех трёх узлах. Это упрощённая учебная реализация:
|
||||
она не гарантирует согласованность при частичных записях и не обрабатывает отказы как промышленная система.
|
||||
Reference in new issue
Block a user