Apache Cassandra
Cassandra — распределённая NoSQL-база с линейной масштабируемостью: петабайты данных, отсутствие единой точки отказа, масштабирование добавлением узлов.
1. Что такое Cassandra
Cassandra построена на архитектуре ring: каждый узел хранит часть данных и равен другим. Запросы обслуживает любая реплика, поэтому нет единой точки отказа (в отличие от MySQL-replica-паттернов).
Модель хранения — «широкая колонка» (column-family): строки по ключам, колонки по времени.
2. Установка
docker run -d --name cass -p 9042:9042 cassandra:4
docker exec -it cass cqlshКонсоль cqlsh — язык CQL (похож на SQL, но со своей логикой ключей).
3. Ключи: partition vs clustering
CREATE KEYSPACE shop
WITH replication = {'class': 'SimpleStrategy',
'replication_factor': 1};
CREATE TABLE shop.users (
user_id UUID,
email text,
name text,
PRIMARY KEY (user_id)
);
CREATE TABLE shop.messages (
user_id UUID,
msg_time timestamp,
body text,
PRIMARY KEY (user_id, msg_time)
) WITH CLUSTERING ORDER BY (msg_time DESC);- Первый ключ — partition key: по нему распределяются строки по узлам.
- Остальные — clustering keys: упорядочивают внутри партиции.
4. Чтение и запись: CRUD
INSERT INTO shop.users (user_id, email, name)
VALUES (uuid(), 'a@example.com', 'Аня');
SELECT * FROM shop.users
WHERE user_id = 11111111-aaaa-0000-0000-000000000000;
UPDATE shop.users SET name = 'Anna' WHERE user_id = ...;
DELETE FROM shop.users WHERE user_id = ...;5. Репликация и стратегии
SimpleStrategy— для одного DC (разработка, тесты).NetworkTopologyStrategy— для продакшна и нескольких дата-центров.
Параметр replication_factor — сколько копий данных хранить. Уровни согласованности: ONE (быстро), QUORUM (надёжно), ALL.
6. Моделирование под запросы
Cassandra не дружит с JOIN'ами и ad-hoc запросами — моделируй таблицы под конкретные обращения (query-first design):
-- таблица под запрос «последние сообщения пользователя»
CREATE TABLE shop.feeds (
user_id UUID,
time_id timeuuid,
text text,
PRIMARY KEY (user_id, time_id)
) WITH CLUSTERING ORDER BY (time_id DESC);Дублируй данные в разные таблицы осознанно — это норма Cassandra.
7. Materialized views и secondary indexes
Индексы по неключевым колонкам и материализованные представления решают часть задач фильтрации. Пользуйся ими аккуратно: на больших партициях они медленны, лучше вторая таблица.
8. Время жизни (TTL)
INSERT INTO shop.sessions (session_id, data)
VALUES (..., 'payload')
USING TTL 3600; # удалится через час9. Кластер и узлы
- Gossip-протокол узнаёт соседей; каждый узел отвечает за свой диапазон ключей (token range).
- Добавление узла: новый токен делит диапазоны — данные перераспределяются автоматически.
- Подтверждение кластера:
nodetool status,nodetool ring.
10. Управляемый сервис и драйверы
- Managed-сервисы: DataStax Astra, AWS Keyspaces.
- Python:
cassandra-driver—cluster.execute('SELECT ...'). - Потоковые задачи — вместе с Spark Connector.
11. Обработка запросов и модель согласованности
Cassandra жертвует строгой согласованностью ради доступности и масштабирования. Понимание, как данные читаются и записываются, поможет выбрать правильный уровень для каждого сценария.
| Уровень | Запись | Чтение | Сценарий |
|---|---|---|---|
| QUORUM | больше половины узлов | сверка на большинстве | базовые операции с сильной гарантией |
| ONE | один узел | мгновенно | высоконагруженный лог, телеметрия |
| LOCAL_ONE | один узел в датацентре | локально | распределённый кластер по DC |
| ALL | все узлы | все узлы | критичные данные (замедляет) |
cqlsh> CONSISTENCY QUORUM;
cqlsh> SELECT * FROM shop.feeds WHERE user_id = ...;12. Data modeling: практические принципы
Модель данных в Cassandra строят «от запроса»: сначала формулируют все паттерны чтения, потом проектируют таблицы под них. Ключевые правила:
- partition key распределяет данные по узлам;
- clustering columns определяют порядок внутри партиции;
- один запрос — одна таблица: денормализация это норма;
- тенди номер: минимум партиций-«горячих», идеально ~100 МБ на партицию.
-- модель «профиль пользователя» под запрос по id
CREATE TABLE shop.users (
user_id UUID PRIMARY KEY,
name text,
email text
);
-- под запрос «все заказы пользователя по убыванию даты»
CREATE TABLE shop.orders_by_user (
user_id UUID,
order_ts timeuuid,
amount decimal,
PRIMARY KEY (user_id, order_ts)
) WITH CLUSTERING ORDER BY (order_ts DESC);13. Tombstones, гарантии и удаление
Удаление в Cassandra не мгновенно: строки помечаются tombstone, затем garbage collection (GC) убирает их через период на основе gc_grace_seconds. Много tombstone'ов замедляют чтения.
-- удалить строку
DELETE FROM shop.feeds WHERE user_id = ... AND time_id = ...;
-- TTL выставляет tombstone автоматически
INSERT INTO shop.sessions (session_id, data)
VALUES (..., 'x') USING TTL 3600;gc_grace_secondsпо умолчанию 10 дней — синхронизация реплик перед GC;- массовая очистка «всем партиция» по TTL — дешёвый приём без tombstone-шторма;
- не удаляйте из таблиц чаще, чем пишете — иначе чтения будут тащить мусор.
nodetool compact при серьёзных чистках.14. Мониторинг и производительность
Cassandra в проде требует наблюдения: нагрузка, задержки, размеры партиций и здоровье узлов. Стандартные команды — ваши первые глаза.
nodetool status # состояние кластера
nodetool ring # распределение токенов
nodetool tpstats # потоки: заблокированные операции
nodetool compactionstats # фоновая компакция
nodetool tablestats keyspace # статистика таблиц| Метрика | Что смотреть |
|---|---|
| p99 read/write latency | задержки не должны взлетать при росте |
| commit log | не переполнен (flush быстрее пишется) |
| сжатие и компакция | проценты и длительность операций |
| память (offheap, JVM) | частично вокруг heap 1–4 ГБ |
15. Lightweight Transactions (LWT)
Cassandra — распределённая база без мгновенной глобальной консистентности: обычный INSERT просто перезапишет данные при конкурентных записях. Для операций «проверь и запиши» используется LWT.
-- создать, только если ключ не существует
INSERT INTO users (id, email) VALUES ('u1', 'a@b.com')
IF NOT EXISTS;
-- atomic conditional update
UPDATE accounts SET balance = balance - 100
WHERE id = 'u1' IF balance >= 100;- LWT работает через Paxos — дороже обычной записи (4-раундовый обмен);
- используйте только там, где правда нужна атомарность;
- apply statement: «IF NOT EXISTS» для уникальности ключей;
- после LWT всегда проверяйте
appliedстолбец в ответе.
16. Counter-таблицы
Счётчики — примитив «увеличить на N» без чтения и без конфликтов: каунтер работает через алгоритм, не теряющий операции при репликации. Это идеально для статистики: просмотры, лайки, эквайринг-счётчики.
CREATE TABLE views (
page_id text PRIMARY KEY,
count counter
);
UPDATE views SET count = count + 1 WHERE page_id = 'home';
-- ответ можно прочитать позже- counter может быть только отдельной колонкой — его нельзя вставлять как обычный;
- counter нельзя сравнивать в LWT-условиях;
- счётчик учитывается на уровне партиции — избегайте горячих;
- точность: для больших приложений слабые gбои возможны — проверьте SLA.
17. Компакция и обслуживание
SSTable-файлы копятся, читатели платят за merge-эффект. Компакция — фоновая пересборка таблиц в более крупные: она освобождает место, ускоряет чтение, но жрёт CPU и диск.
| Стратегия | Когда выбрать |
|---|---|
| SizeTiered (STCS) | классика для больших таблиц |
| Leveled (LCS) | постоянные небольшие SSTable, мало tombstones |
| TimeWindow (TWCS) | временны́е ряды с TTL |
- контролируйте
nodetool compactionstats; - периодический
nodetool repair— для консистентности; - не запускайте compact одновременно с большим repair;
- GC Grace: рано почищенные tombstones разрывают чтения — держите разумное.
major compaction на больших кластерах перегружает диск. Разрешайте её в окно низкой нагрузки и только после re-estimate.18. Безопасность: роли и TLS
По умолчанию Cassandra открыта: любой клиент может читать и писать. Для прода настройте авторизацию (пароль/роли) и шифрование канала (TLS) между клиентами и нодами.
# Cassandra.yaml
authenticator: PasswordAuthenticator
authorizer: CassandraAuthorizer
client_encryption_options:
enabled: true
keystore: conf/.keystore
truststore: conf/.truststore
# создать пользователя и права
CREATE ROLE analyst WITH PASSWORD = 'secret' LOGIN;
GRANT SELECT ON keyspace1.table1 TO analyst;- правило «минимум прав»: роль читает только своё keyspace;
- периодически проверяйте, не упал ли дефолтный cassandra/cassandra;
- шифруйте трафик нод — данные не должны лететь открытыми по кластерной сети;
- для секретов используйте секрет-менеджеры, а не переменные в .yaml.
19. Время жизни данных (TTL) на практике
TTL — время жизни строки: данные автоматически исчезают через заданный срок. Это изящное решение для сессий, логов и временных меток, но с нюансами.
-- вставить строку, которая живёт сутки
INSERT INTO sessions (id, data) VALUES (uuid(), 'payload') USING TTL 86400;
-- обновление с новым TTL
UPDATE sessions USING TTL 3600 SET data = 'new' WHERE id = ...- TTL ставится на ячейку или строку, счёт начинается с момента записи;
- рекомендуется ставить про запас на большие диапазоны дат;
- истёкшие строки остаются как tombstones до компакции;
- нельзя поставить «бессрочный» TTL — есть максимум ~3 лет.
20. Антипаттерны моделирования данных
Cassandra не любит запросы «по индексам как в SQL»: частые антипаттерны ломают производительность. Их проще избежать, если знать их заранее.
- вторичные индексы на высоконагруженных колонках — путь к медленным запросам;
- слишком широкие партиции: миллионы строк в одной партиции = горячая точка;
- запросы на диапазоны по неключевым колонкам — заставляют full scan;
- многократные джойны «как в реляционной» — не про Cassandra.
21. Boost производительности: настройка ключевых параметров
Исправная модель — полдела. Вторая половина — настройки: memtable, кэш, партиции и сеть. Оптимизация начинается с конфигурации, а не с покупки новых нод.
- ключевые параметры: memtable_cleanup_threshold, key_cache_size_in_mb;
- настройки compaction: SizeTiered для записи, Leveled для чтения;
- read repair и hints — фоновая механика согласованности;
- мониторинг: nodetool tpstats, cfstats, tablestats.
nodetool tpstats # потоки и очереди
nodetool tablehistograms ks.tbl # метрики чтения/записи22. Миграция данных и перенос кластера
Переезд между кластерами — частая задача: смена провайдера, версии или структуры. План миграции бережёт время и данные.
- сначала прогоните полный snapshot и резервную копию уникальных ключей;
- переносите данные по таблицам: COPY для малых, sstable2sstable для больших;
- перенос схемы: describe + restore keyspace;
- переключение клиентов: приложений по очереди, следите за лагом репликации;
- оставляйте старый кластер читаемым до стабильного переключения.
Что дальше
Сравни схемы данных с MongoDB и Redis. Для очередей событий — Kafka.