open atlas
↑ К треку
Основы System Design SD · 04 · 07

Распределение данных: чтение конфига и кода

Читай реальный конфиг репликации, выбор ключа партиционирования, функцию маршрутизации и настройку кворума, затем рассуждай: найди риск потери записи, горячий шард, ловушку mod-N решардинга и гарантирует ли кворум свежее чтение.

SD Senior ◷ 14 min
Уровень
ОсновыJuniorMiddleSenior

Баги распределения живут в конфиге и коде маршрутизации: режим репликации, ключ партиционирования, модуль, число кворума. Читай каждый сниппет, проследи режим отказа, который он подразумевает, и выбери ответ, на который senior-инженер пойдёт на ревью.

Отработай цикл, что гоняешь на ревью дизайна или инцидента: найди решение распределения в конфиге или коде, проследи его режим отказа и выбери изменение, которое механизм реально поддерживает.

Сниппет 1 — конфиг репликации

# репликация базы
replication:
  mode: async          # лидер подтверждает до получения записи фолловерами
  followers: 3
  sync_replicas: 0     # ни один не обязан подтвердить
# при отказе лидера: автоповышение самого догнавшего фолловера
Викторина

Какой риск долговечности несёт этот конфиг и какое минимальное изменение?

Сниппет 2 — ключ партиционирования

# таблица events шардирована; выбери ключ шарда
def shard_for(event):
    return hash(event.created_at_day) % NUM_SHARDS   # шард по дню
# самый горячий запрос: SELECT ... WHERE tenant_id = ? AND created_at_day = ?
Викторина

Что не так с шардированием events по created_at_day при такой нагрузке?

Сниппет 3 — функция маршрутизации

# клиент кеша выбирает узел для каждого ключа
def node_for(key, nodes):
    return nodes[hash(key) % len(nodes)]   # nodes — живой автомасштабируемый список

# автоскейлер добавляет/убирает узлы кеша по нагрузке
Викторина

Флот кеша автомасштабируется, так что len(nodes) меняется в рантайме. Что вызывает эта маршрутизация и какая починка?

Сниппет 4 — настройка кворума

# leaderless key-value хранилище
N = 5          # реплик на ключ
W = 2          # узлов должны подтвердить запись
R = 2          # узлов должны ответить на чтение
# требование продукта: чтение всегда должно видеть последнюю подтверждённую запись
Викторина

Удовлетворяет ли W = 2, R = 2 при N = 5 требованию, и если нет — какая минимальная верная настройка?

Вспомните перед уходом
  1. 01
    Как читать риск долговечности по конфигу репликации?
  2. 02
    Почему hash(key) % len(nodes) небезопасен для автомасштабируемого набора узлов и что его заменяет?
  3. 03
    Имея N, W, R, как понять, гарантированно ли свежи чтения, и какова минимальная починка, когда нет?
Итог

Каждое решение распределения в этом юните — то, что можно прочитать прямо из конфига или кода маршрутизации. Конфиг репликации с mode: async и sync_replicas: 0 подтверждает до того, как у любого фолловера есть запись, так что failover теряет подтверждённые записи — починка — одна синхронная реплика. Ключ партиционирования, выбранный против нагрузки (шардинг events по дню, когда горячий запрос фильтрует по tenant), создаёт горячую точку записи и немаршрутизируемый запрос — переведи ключ под паттерн доступа. Функция маршрутизации hash(key) % len(nodes) над автомасштабируемым набором узлов переотображает почти все ключи при каждом событии скейла — замени её кольцом consistent hashing, чтобы двигалось лишь ~1/N. А кворум гарантирует свежее чтение лишь когда R + W > NW = 2, R = 2, N = 5 (сумма 4) нет, а W = 3, R = 3 (сумма 6) да. Senior-привычка — найти решение распределения в конфиге, проследить его режим отказа и выбрать починку, которую механизм поддерживает, — а не ту, что его прячет.

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.