← Назад к вопросам

Почему не использовали Apache Cassandra?

2.0 Middle🔥 71 комментариев
#Кэширование и NoSQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Почему не использовали 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 только если:

  1. Вы явно достигли её limit
  2. У вас есть ресурсы на поддержку кластера
  3. Выигрыш в масштабируемости оправдывает сложность