Распределение данных: шардируй, реплицируй и сломай
Практический проект: возьми датасет, спроектируй ключ партиционирования и репликацию, построй крошечное шардированное хранилище на consistent hashing, затем намеренно вызови горячий шард, потерю записи при failover и устаревшее кворумное чтение — и докажи, что меры работают.
Прочитать, что async-failover теряет записи и что mod-N рушит решардинг, — не то же, что увидеть это на хранилище, которое ты построил. Возьми датасет, спроектируй ключ партиционирования и репликацию, реализуй крошечное шардированное key-value хранилище на consistent hashing, а затем намеренно воспроизведи три фирменных отказа юнита — горячий шард, потерю записи и устаревшее кворумное чтение — и докажи, что твои меры реально закрывают каждый.
Этот проект делает весь юнит операциональным: ты выберешь ключ партиционирования и режим репликации, замаршрутизируешь ключи кольцом, а затем вызовешь каждый отказ намеренно, чтобы мера была чем-то измеренным, а не прочитанным.
Спроектируй и построй крошечное распределённое key-value хранилище (любой язык, в процессе или мультипроцессно), которое шардирует данные по выбранному ключу партиционирования, маршрутизирует ключи через consistent hashing и реплицирует каждый шард — затем намеренно воспроизведи горячий шард, потерю записи при failover и устаревшее кворумное чтение, и продемонстрируй меру для каждого.
- Абзац брифа с доминирующим запросом, отношением чтений к записям и кардинальностью ключа плюс обоснованный ключ партиционирования, выбранный из паттерна доступа.
- Измерение, показывающее, что consistent hashing двигает ~1/N ключей при смене членства против базлайна mod-N, двигающего почти все — с приведёнными реальными долями.
- Воспроизведённый горячий шард (нагрузка одного шарда сильно выше остальных при перекосе) и измерение после, показывающее, что мера размазала нагрузку.
- Воспроизведённая потеря записи при async-failover и повтор при полусинхроне, где та же подтверждённая запись выживает — с точной последовательностью, давшей каждый исход.
- Демонстрация кворума: устаревшее чтение при R + W ≤ N и гарантированно свежее чтение при R + W > N, с использованными значениями N, W, R.
- Короткая заметка об архитектурных решениях, связывающая каждый выбор (ключ, режим репликации, кворум, точка CAP/PACELC) с конкретной гарантией или компромиссом, что он покупает.
- Добавь split-brain: раздели кластер на партиции, дай обеим сторонам принимать записи, затем заживи и покажи разошедшиеся истории — и реализуй fencing или кворумное повышение, не дающее второму лидеру принимать записи.
- Добавь путь решардинга: вырасти кольцо с N до N+2 узлов под живыми записями через двойную запись или change-data-capture и покажи, что ни одна подтверждённая запись не потеряна во время cutover.
- Добавь bounded-load consistent hashing (ограничь каждый узел c×среднее и переливай по часовой) и покажи, что он укрощает горячий шард для маршрутизации запросов, сохраняя свойство движения ~1/N.
- Добавь мульти-лидерный режим с двумя регионами, принимающими записи, инжектируй конфликтующую параллельную запись и реализуй разрешение конфликта (last-write-wins против вектора версий) — обсуждая, какое тихо теряет данные.
- 01Как показать, что consistent hashing бьёт mod-N при смене членства?
- 02Какая точная последовательность даёт потерю записи при async-failover и как полусинхрон её чинит?
- 03Как показать, что кворум гарантирует (или не гарантирует) свежее чтение?
Этот проект превращает юнит распределения данных в то, что ты эксплуатировал, а не лишь прочитал. Ты выбираешь ключ партиционирования из доминирующего паттерна доступа и кардинальности, маршрутизируешь ключи по кольцу consistent hashing с виртуальными узлами (и измеряешь движение ~1/N против базлайна mod-N, переотображающего почти все), и реплицируешь каждый шард в синхронном и асинхронном режимах. Затем ты воспроизводишь три фирменных отказа юнита намеренно и закрываешь каждый: горячий шард при перекосе (смягчён разбивкой, кешированием или изоляцией ключа-знаменитости), потерю записи при async-failover (починена полусинхроном, чтобы ack означал «на двух узлах») и устаревшее кворумное чтение при R + W ≤ N (починено R + W > N, чтобы множества чтения и записи пересекались). Заметка об архитектурных решениях связывает каждый выбор — ключ, режим репликации, кворум, точку CAP/PACELC — с конкретной гарантией, что он покупает. Инженер, однажды построивший и сломавший это хранилище, распределяет данные намеренно, выбирая, какое расхождение терпеть, заранее, вместо того чтобы обнаруживать потерянную запись или снесённый кеш во время failover в 3 ночи.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.