Почему не использовали Apache Cassandra?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Почему не использовали Apache Cassandra
Apache Cassandra — это мощная распределённая база данных, но она далеко не универсальное решение. Выбор между Cassandra и альтернативами (PostgreSQL, MongoDB, DynamoDB) зависит от конкретных требований проекта.
Основные причины отказа от Cassandra
1. Complexity Overhead для небольших проектов
Cassandra требует кластеризации как минимум из 3 узлов для обеспечения надёжности. Для небольшого проекта это:
- Усложнённое развёртывание
- Высокие затраты на инфраструктуру
- Сложность мониторинга и отладки
// Даже подключение требует работы с кластером
Session session = cluster.connect("keyspace_name");
PreparedStatement ps = session.prepare(
"INSERT INTO users (id, name, email) VALUES (?, ?, ?)"
);
Для стартапа или MVP-фазы это слишком тяжело.
2. Eventually Consistent Model
Cassandra использует модель итоговой согласованности (eventual consistency), а не строгую согласованность:
Поток A: INSERT user (id=123, name="Ivan")
↓
Записывается на узел 1 ✓
Записывается на узел 2... (ещё в процессе)
Поток B: SELECT * FROM users WHERE id=123 (читает узел 3)
↓
Может получить СТАРЫЕ данные или отсутствие записи!
Для приложений, которым нужна немедленная согласованность (финансовые системы, банкинг, заказы), это неприемлемо. PostgreSQL гарантирует ACID из коробки.
3. Отсутствие JOIN операций
Cassandra не поддерживает JOIN — это фундаментальное ограничение её архитектуры:
-- PostgreSQL - просто
SELECT u.name, o.order_id
FROM users u
JOIN orders o ON u.id = o.user_id;
-- Cassandra - нужно делать в приложении
Session session = cluster.connect();
ResultSet users = session.execute("SELECT id, name FROM users");
for (Row user : users) {
long userId = user.getLong("id");
ResultSet orders = session.execute(
"SELECT order_id FROM orders WHERE user_id = ?", userId
); // N+1 queries!
}
Проблема N+1 queries приводит к:
- Низкой производительности
- Высокой нагрузке на сеть
- Сложному и громоздкому коду
4. Сложность с транзакциями
Cassandra 3.0+ добавила Lightweight Transactions (LWT), но это с оговорками:
// LWT в Cassandra - медленно и сложно
BoundStatement bs = preparedStatement.bind(
userId, newEmail
);
bs.setIdempotent(false);
bs.setConsistencyLevel(ConsistencyLevel.QUORUM);
ResultSet rs = session.execute(bs);
Row row = rs.one();
if (row.getBool("[applied]")) {
// Транзакция применена
} else {
// Конфликт - нужна логика отката
}
При необходимости многоступенчатых транзакций это становится кошмаром. PostgreSQL справляется естественно:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
5. Операционная сложность
Cassandra требует глубокого понимания её особенностей:
- Кольцевая топология (ring topology)
- Репликация данных и хеширование
- Tuning jvm.options, cassandra.yaml
- Batch operations и их правильное использование
- Garbage Collection проблемы
Ошибка в конфигурации может привести к:
- Потере данных
- Расколу кластера (split-brain)
- Неконтролируемому росту памяти
6. Ограничения на размер partition
Cassandra не позволяет иметь очень большие партиции:
Одна партиция может содержать
максимум ~2 млрд ячеек
(зависит от конфигурации, но это потолок)
Если вам нужна горячая партиция (например, все события пользователя в одном key), Cassandra может выполняться неоптимально.
7. Дороговизна отладки
Дебаг распределённых систем сложен:
// Как вы узнаете, на каком узле находятся данные?
Token token = new Murmur3Token();
long hashValue = token.getTokenValue();
// Какой узел отвечает за этот диапазон?
// Где произошла репликация?
// Есть ли мёртвые узлы?
// В PostgreSQL: psql, logfile и SQL - вот и всё
Когда ВСЁ-ТАКИ использовать Cassandra
Cassandra отлична для:
- Time-series data (метрики, логи, события) — гигабайты данных в день
- Высокая писательская нагрузка — 100k+ requests per second
- Географическая распределённость — разные дата-центры
- Горизонтальное масштабирование из коробки
- Высокая доступность без SPOF
Альтернативы
┌─────────────────────┬──────────────────┬──────────────────┐
│ Сценарий │ PostgreSQL │ Cassandra │
├─────────────────────┼──────────────────┼──────────────────┤
│ Стартап / MVP │ ✓✓✓ │ ✗✗✗ │
│ ACID транзакции │ ✓✓✓ │ ✗✗ │
│ JOIN операции │ ✓✓✓ │ ✗✗✗ │
│ Time-series │ ✗✗ │ ✓✓✓ │
│ High throughput │ ✗✗ │ ✓✓✓ │
│ Простота операций │ ✓✓✓ │ ✗✗ │
│ Диапазонные query │ ✓✓✓ │ ✗✗ │
│ Отладка │ ✓✓✓ │ ✗✗ │
└─────────────────────┴──────────────────┴──────────────────┘
Резюме
Cassandra — это специализированная база данных для специфических задач (распределённые системы, высокие нагрузки, time-series), а не универсальное решение. Для большинства приложений на Java рекомендуется начинать с PostgreSQL или MySQL, и переходить на Cassandra только если:
- Вы явно достигли её limit
- У вас есть ресурсы на поддержку кластера
- Выигрыш в масштабируемости оправдывает сложность