Налаштування Apache Cassandra для високонавантажених веб-додатків
Конфігурація Apache Cassandra для веб-додатку потребує не просто встановлення пакета. Без грамотного проектування схеми та налаштувань кластера ви отримаєте повільні запити, гарячі партиції та нестабільну роботу під навантаженням. За 5 років роботи ми налаштували Cassandra для 30+ проектів: стрічки подій, метрики, логи. Найпоширеніша помилка — неправильний первинний ключ. Ігнорування компрессії та недостатня пам'ять для memtable призводять до падіння продуктивності в 2–3 рази. Правильне налаштування Cassandra з першого разу економить тижні переробок. Ділимося перевіреними прийомами.
Де Apache Cassandra незамінна
Часові ряди з мільйонами подій на секунду, стрічки активності, системи логування, IoT-телеметрія — там, де потрібно писати швидко та багато. Netflix, Discord, Apple використовують Cassandra саме для цього. Discord зберігає трильйони повідомлень. Для OLTP зі складними транзакціями — не підходить. Ми застосовуємо Cassandra для зберігання метрик та логів: вона дає лінійне масштабування запису та відмовостійкість без єдиної точки відмови.
Налаштування Cassandra 4.1: встановлення та конфігурація
Як встановити Cassandra 4.1?
- Додайте репозиторій:
echo "deb https://debian.cassandra.apache.org 41x main" > /etc/apt/sources.list.d/cassandra.sources.list - Імпортуйте ключ:
curl https://downloads.apache.org/cassandra/KEYS | apt-key add - - Встановіть пакет:
apt update && apt install -y cassandraПісля встановлення відредагуйте
cassandra.yaml:cluster_name: 'MyAppCluster' # Мережа listen_address: 10.0.0.1 rpc_address: 10.0.0.1 seeds: "10.0.0.1,10.0.0.2,10.0.0.3" # Директорії data_file_directories: - /var/lib/cassandra/data commitlog_directory: /var/lib/cassandra/commitlog # окремий диск для швидкості hints_directory: /var/lib/cassandra/hints saved_caches_directory: /var/lib/cassandra/saved_caches # Продуктивність concurrent_reads: 32 concurrent_writes: 32 concurrent_counter_writes: 16 memtable_heap_space: 2048 compaction_throughput_mb_per_sec: 64 # Реплікація та консистентність endpoint_snitch: GossipingPropertyFileSnitch # JVM (в jvm11-server.options) num_tokens: 256Додатково налаштуйте JVM, щоб уникнути довгих GC-пауз:
# /etc/cassandra/jvm11-server.options -Xms8G -Xmx8G -XX:+UseG1GC -XX:G1RSetUpdatingPauseTimePercent=5 -XX:MaxGCPauseMillis=300 -XX:InitiatingHeapOccupancyPercent=70Як вибрати стратегію компресії?
Порівняння стратегій ущільнення:
Стратегія Призначення Коли використовувати SizeTieredCompactionStrategy За замовчуванням Універсальний варіант, підходить для більшості випадків TimeWindowCompactionStrategy Часові ряди Дані з TTL, стрічки подій — зменшує кількість файлів LeveledCompactionStrategy Часті оновлення Системи з великою кількістю записів, потребує більше дискового простору Вибір компрессії безпосередньо впливає на продуктивність читання та запису. Наприклад, TimeWindowCompactionStrategy зменшує кількість SSTable в 2–3 рази порівняно з SizeTieredCompactionStrategy при роботі з часовими рядами. Ми рекомендуємо TimeWindowCompactionStrategy для даних з TTL, а LeveledCompactionStrategy — для сценаріїв з інтенсивними оновленнями. Остання працює на 50% швидше за умови частих оновлень.
Орієнтуйтеся на характер даних. Якщо дані мають TTL і записуються з постійною швидкістю — TimeWindowCompactionStrategy. Для частих оновлень та видалень — LeveledCompactionStrategy. SizeTieredCompactionStrategy — безпечний вибір, якщо не впевнені.
Важливість правильного ключа партиціонування
Ключ партиціонування визначає розподіл даних по вузлах. Якщо він вибраний неправильно, одні вузли будуть перевантажені, інші простоюють. Наприклад, для таблиці
user_eventsми використовуємоuser_id— це гарантує рівномірний розподіл. Для часових рядів (таблицяmetrics) складений ключ(service, bucket, metric_name)дозволяє згрупувати метрики по сервісу та часовому вікну. Ніколи не використовуйте стовпці з малою кількістю унікальних значень (boolean або enum) — це призведе до гарячих партицій.Схема даних — Query-driven design
-- Keyspace з реплікацією CREATE KEYSPACE myapp WITH replication = { 'class': 'NetworkTopologyStrategy', 'dc1': 3 } AND durable_writes = true; USE myapp; -- Стрічка подій користувача CREATE TABLE user_events ( user_id uuid, occurred_at timestamp, event_id uuid, event_type text, payload text, PRIMARY KEY ((user_id), occurred_at, event_id) ) WITH CLUSTERING ORDER BY (occurred_at DESC) AND compaction = {'class': 'TimeWindowCompactionStrategy', 'compaction_window_unit': 'DAYS', 'compaction_window_size': 7} AND default_time_to_live = 7776000; -- Статистика по користувачах CREATE TABLE user_stats ( user_id uuid PRIMARY KEY, total_orders counter, total_spent counter, last_active timestamp ); -- Часові ряди метрик CREATE TABLE metrics ( service text, bucket timestamp, metric_name text, ts timestamp, value double, PRIMARY KEY ((service, bucket, metric_name), ts) ) WITH CLUSTERING ORDER BY (ts DESC) AND compaction = {'class': 'TimeWindowCompactionStrategy', 'compaction_window_unit': 'HOURS', 'compaction_window_size': 1};Як інтегрувати Cassandra з Node.js?
import cassandra from 'cassandra-driver' const client = new cassandra.Client({ contactPoints: ['10.0.0.1', '10.0.0.2', '10.0.0.3'], localDataCenter: 'dc1', keyspace: 'myapp', credentials: { username: 'cassandra', password: process.env.CASSANDRA_PASSWORD! }, pooling: { coreConnectionsPerHost: { [cassandra.types.distance.local]: 3, [cassandra.types.distance.remote]: 1 } }, socketOptions: { readTimeout: 12000 } }) await client.connect() const insertEvent = await client.prepare(` INSERT INTO user_events (user_id, occurred_at, event_id, event_type, payload) VALUES (?, ?, ?, ?, ?) `) const selectEvents = await client.prepare(` SELECT * FROM user_events WHERE user_id = ? AND occurred_at >= ? AND occurred_at <= ? ORDER BY occurred_at DESC LIMIT ? `) async function writeEvents(events: UserEvent[]) { const batch = events.map(e => ({ query: insertEvent, params: [ cassandra.types.Uuid.fromString(e.userId), new Date(e.occurredAt), cassandra.types.TimeUuid.now(), e.eventType, JSON.stringify(e.payload) ] })) await client.batch(batch, { prepare: true, logged: false }) } async function* fetchEvents(userId: string, from: Date, to: Date) { const options = { prepare: true, fetchSize: 1000 } let pageState: Buffer | undefined do { const result = await client.execute(selectEvents, [cassandra.types.Uuid.fromString(userId), from, to, 1000], { ...options, pageState }) yield result.rows pageState = result.pageState as Buffer | undefined } while (pageState) }Рівні консистентності
Рівень Швидкість Надійність Приклад використання ONE Швидко Низька Аналітика, кеш LOCAL_QUORUM Середньо Висока Операції запису QUORUM Повільно Максимальна Критичні дані const { types: { consistencies } } = cassandra await client.execute(insertEvent, params, { consistency: consistencies.localQuorum }) await client.execute(selectEvents, params, { consistency: consistencies.one }) await client.execute(criticalQuery, params, { consistency: consistencies.quorum })Моніторинг та діагностика
nodetool status nodetool tpstats nodetool cfstats myapp.user_events nodetool compactionstats nodetool cleanup myappУвімкніть повільні запити в
cassandra.yaml:slow_query_log_timeout_in_ms: 500.Типові помилки та їх вирішення
- Гарячі партиції через неправильний ключ: використовуйте складені ключі з високою кардинальністю. Уникайте стовпців з малою кількістю значень.
-
Високе споживання пам'яті: зменшіть
memtable_heap_spaceабо перемкніть G1GC на ParallelGC. Економія пам'яті до 30%. -
Повільний запис: перевірте диск для commitlog — використовуйте окремий SSD. Збільшіть
concurrent_writes.
Практичні аспекти та варіанти співпраці
Типовий проект з трьома вузлами та інтеграцією займає 2–3 тижні. Включає аудит вимог, проектування схеми, розгортання кластера, оптимізацію конфігурації та написання адаптера для бекенда. Складні кластери з кількома дата-центрами можуть потребувати до 5 тижнів. Отримайте точну оцінку під вашу задачу — напишіть нам.
Ми виконали понад 30 проектів з Cassandra, включаючи системи метрик для рекламної платформи (100 млн подій на добу) та стрічки активності для SaaS-сервісу. У кожному проекті ми гарантуємо стабільну роботу кластера протягом місяця після здачі. Наші інженери мають 5+ років досвіду з Cassandra та суміжними технологіями. Зв'яжіться з нами для консультації — обговоримо вашу архітектуру безкоштовно.
Що входить в роботу
- Аудит поточної архітектури та вимог до навантаження
- Проектування схеми даних (query-driven design)
- Розгортання кластера (bare-metal / хмара / Docker)
- Оптимізація
cassandra.yaml, JVM та мережевих налаштувань - Інтеграція з бекендом (Node.js, Python, Go)
- Документація схеми та інструкції з експлуатації
- Навчання команди та рекомендації з експлуатації
- Гарантія стабільної роботи кластера протягом місяця після здачі
Замовте налаштування Cassandra під вашу задачу — отримайте консультацію інженера з 5-річним досвідом. Вартість типового проекту — від €2000.







