Базы данных

Cassandra: wide-column для петабайтных данных

Netflix хранит данные о 36 петабайтах просмотров в Cassandra. Когда 200 миллионов подписчиков одновременно смотрят что-то в пятничный вечер - Cassandra обрабатывает миллионы writes в секунду без единого мастер-узла, без единой точки отказа. Ни PostgreSQL, ни MySQL не масштабируются так линейно.

  • **Apple iCloud**: 75000+ Cassandra узлов, хранение данных 782 млн устройств - крупнейший известный Cassandra кластер
  • **Discord**: 4 триллиона сообщений в Cassandra; в 2023 мигрировали на ScyllaDB (C++ реализация Cassandra API) для лучшей производительности
  • **Uber**: история поездок и GPS треки в Cassandra - миллиарды строк с предсказуемым <10ms latency

Partition Key и Clustering Key

Cassandra PRIMARY KEY состоит из двух частей: partition key определяет на каком узле хранятся данные (через Murmur3 hash), clustering key определяет порядок строк внутри партиции. Все строки с одинаковым partition key хранятся на одном узле и читаются за один disk seek.

Горячая партиция (hot partition) - главная проблема Cassandra. Если partition key - это дата, все сегодняшние записи идут в одну партицию = один перегруженный узел. Решение: добавить bucket в ключ: (date, bucket) где bucket = random(0, N).

Таблица message с PRIMARY KEY (chat_id, message_id). Что произойдёт если в чате миллион сообщений?

Gossip Protocol и Ring Architecture

Cassandra - peer-to-peer кластер без master. Узлы образуют кольцо (ring), каждый узел ответственен за диапазон токенов. Gossip protocol - механизм discovery: каждую секунду каждый узел 'сплетничает' со случайными соседями о состоянии кластера. За O(log N) раундов информация распространяется по всему кластеру.

Consistent hashing в Cassandra: при добавлении узла перемещается только 1/N данных, не весь кластер. Virtual nodes (vnodes) улучшают распределение: каждый физический узел отвечает за множество небольших диапазонов токенов, что делает балансировку почти идеальной.

Cassandra кластер из 6 узлов, replication factor = 3. Сколько узлов могут упасть без потери доступности данных?

Уровни консистентности

Cassandra жертвует строгой консистентностью ради availability (AP в CAP). Но уровень консистентности настраивается для каждого запроса. ONE - читает/пишет на 1 узел (быстро, возможен stale read). QUORUM - большинство реплик (баланс). ALL - все реплики (медленно, но строго). LOCAL_QUORUM - quorum в датацентре без cross-DC.

Cassandra LWT (Lightweight Transactions) добавляют compare-and-set операции: INSERT IF NOT EXISTS, UPDATE IF условие. Под капотом используется Paxos - дорогостоящий протокол. Использовать только когда нужна строгая консистентность (например, уникальность username).

Приложение пишет платёж с CONSISTENCY ONE и сразу читает его с CONSISTENCY ONE. Почему возможен 'not found'?

Стратегии компакции

Cassandra использует LSM-tree: сначала в memtable (память), потом flush на диск в SSTable (immutable). Со временем SSTables накапливаются, чтение замедляется. Compaction объединяет SSTables и удаляет tombstones (метки удалённых данных).

СтратегияКогда использоватьTrade-off
STCS (Size-Tiered)Write-heavy, append-onlyБыстрая запись, медленное чтение при большом объёме
LCS (Leveled)Read-heavy, много обновленийМедленная запись, быстрое чтение, предсказуемый размер
TWCS (Time-Window)Time-series данные с TTLЭффективное удаление устаревших данных целыми файлами

Discord использует Cassandra с TWCS для хранения сообщений с TTL. Когда окно времени закрывается, весь SSTable удаляется без дорогостоящего компакции. Это позволяет хранить 4 триллиона сообщений при разумных затратах на хранение.

Таблица метрик: данные записываются непрерывно, хранятся 30 дней, потом удаляются. Какая стратегия компакции?

Data Modeling в Cassandra

Главное правило Cassandra data modeling: модель определяется запросами, а не сущностями. В SQL сначала нормализуют данные, потом пишут любые запросы. В Cassandra сначала определяют запросы, под каждый запрос создают отдельную таблицу с нужным partition key.

Cassandra не поддерживает JOINs и subqueries. Если запрос требует JOIN - нужно денормализовать данные при записи (Materialized View Pattern). Запись немного дороже, зато чтение всегда быстрое и предсказуемое.

Cassandra - просто масштабируемый MySQL

Cassandra требует полного переосмысления data modeling. Нет JOIN, нет произвольных WHERE, нет транзакций. Зато: линейное масштабирование, нет single point of failure, петабайты данных.

Разработчики с SQL бэкграундом пытаются использовать Cassandra как реляционную БД. Это приводит к ALLOW FILTERING, secondary index антипаттернам и медленным запросам. Query-first моделирование - ключевой навык.

В Cassandra нужно получить заказы пользователя за последние 7 дней. Какой подход правильный?

Ключевые идеи

  • **Partition Key**: определяет узел хранения, должен иметь высокую cardinality и равномерное распределение - горячая партиция = узкое место
  • **Consistency Levels**: ONE (быстро, eventual), QUORUM (баланс), ALL (медленно, строго) - выбор для каждого запроса
  • **Query-first modeling**: под каждый запрос - отдельная таблица; денормализация и дублирование данных - норма, не антипаттерн

Связанные темы

Cassandra строится на нескольких фундаментальных концепциях:

  • LSM-Tree — Cassandra использует LSM-tree для всех операций записи - memtable + SSTables
  • CAP теорема — Cassandra - AP система: availability и partition tolerance за счёт eventual consistency
  • Time-series базы данных — Cassandra с TWCS - популярный выбор для time-series при нагрузке выше TimescaleDB

Вопросы для размышления

  • Система аналитики: миллион событий в секунду, нужен count по user_id за последний час. Как смоделировать в Cassandra?
  • Когда стоит выбрать Cassandra вместо PostgreSQL даже при небольшом объёме данных?
  • Cassandra гарантирует 'eventual consistency'. Что это означает для пользователя приложения на практике?

Связанные уроки

  • dist-15-consistent-hashing
Cassandra: wide-column для петабайтных данных

0

1

Войти