Перейти к основному содержимому

3.06. Справочник по Cassandra

Разработчику Аналитику Тестировщику
Архитектору Инженеру

Справочник по Cassandra

I. Настройки cassandra.yaml — основной конфигурационный файл Cassandra

Файл cassandra.yaml содержит большинство параметров поведения узла Cassandra. Изменение большинства параметров требует перезапуска узла. Ниже приведены ключевые свойства, сгруппированные по смысловым блокам, с пояснением назначения и допустимых значений.

1. Идентификация узла и кластера

  • cluster_name — строковое имя кластера. Все узлы, входящие в один логический кластер, должны иметь одинаковое значение. По умолчанию: 'Test Cluster'. Рекомендуется задавать осмысленное имя, например 'Production-Analytics'. Изменение этого параметра после инициализации узла приводит к невозможности присоединения к кластеру.

  • num_tokens — количество виртуальных токенов (vnodes), которыми владеет узел. Определяет, сколько диапазонов кольца хэш-пространства будет обслуживать узел. По умолчанию: 256. Уменьшение увеличивает нагрузку на узел, но уменьшает число перебалансировок при добавлении/удалении. Значения от 1 до 1024. При num_tokens: 1 используется физическая схема токенизации (устаревшая, требует ручного управления initial_token).

  • initial_token — явное указание начального токена при использовании num_tokens: 1. Формат — шестнадцатеричное число в диапазоне от 0 до 2^127-1. Например: '85070591730234615865843651857942052864'. Не используется при num_tokens > 1.

  • listen_address — IP-адрес интерфейса, на котором узел слушает внутренние запросы кластера (Gossip, streaming). Должен быть доступен для всех других узлов. По умолчанию: 'localhost'. Рекомендуется явно задавать, особенно в production. Может быть 0.0.0.0, но это небезопасно.

  • rpc_address — IP-адрес, на котором узел слушает клиентские соединения (Native Transport Protocol, т.е. CQL). По умолчанию: 'localhost'. Для внешнего подключения — явное указание, например '192.168.1.10' или '0.0.0.0'.

  • broadcast_address, broadcast_rpc_address — адреса, которые узел объявляет другим узлам и клиентам. Используются в случае NAT или когда listen_address/rpc_address — внутренние адреса, но внешние клиенты/узлы должны обращаться по другому. Оба принимают строковые значения IPv4/IPv6.

2. Параметры хранилища и каталогов

  • data_file_directories — список путей к директориям для размещения SSTable-файлов (основные данные). Может быть одна или несколько директорий — Cassandra умеет распределять данные по ним (round-robin). Пример:

    data_file_directories:
    - /var/lib/cassandra/data1
    - /var/lib/cassandra/data2

    При наличии нескольких дисков это улучшает параллелизм ввода-вывода.

  • commitlog_directory — путь к директории для commit log. Записи в commit log последовательны, поэтому рекомендуется размещать на отдельном физическом диске с высокой скоростью записи (например, SSD). По умолчанию: /var/lib/cassandra/commitlog.

  • saved_caches_directory — директория для сохранённых кэшей (row cache, key cache, counter cache). По умолчанию: /var/lib/cassandra/saved_caches. Кэши могут быть восстановлены при старте.

  • hints_directory — путь для хранения hinted handoff-файлов. Используется при временной недоступности узла: координатор сохраняет изменения и позже отправляет их, когда узел вернётся. По умолчанию: /var/lib/cassandra/hints.

3. Параметры сетевого взаимодействия

  • storage_port — порт для внутреннего межузлового общения (Gossip протокол, streaming). По умолчанию: 7000. Для SSL-трафика используется ssl_storage_port: 7001.

  • native_transport_port — порт для клиентских CQL-соединений (Binary Protocol). По умолчанию: 9042. Именно к этому порту подключается cqlsh, драйверы и т.д.

  • native_transport_max_threads — максимальное количество потоков для обработки входящих CQL-запросов. По умолчанию: 128. При высокой нагрузке может быть увеличено, но рост ограничен пропускной способностью CPU и дисковой подсистемы.

  • native_transport_max_frame_size_in_mb — максимальный размер единичного CQL-фрейма. Ограничивает размер одного запроса или результата. По умолчанию: 256. Превышение приводит к InvalidRequestException.

  • start_native_transport — включает/выключает CQL-сервер. Булево: true/false. По умолчанию: true. Может быть отключён в debug-сценариях.

  • start_rpc — включает устаревший Thrift-сервер (RPC-порт 9160). По умолчанию: false (начиная с версии 4.0). Thrift устарел, не рекомендуется использовать.

4. Параметры репликации и согласованности

  • endpoint_snitch — класс, определяющий топологию кластера (какие узлы находятся в одном датацентре, стойке и т.д.). Влияет на стратегию репликации и выбор узлов-координаторов.
    Допустимые значения:

    • SimpleSnitch — игнорирует топологию; подходит только для single-DC dev-окружений.
    • GossipingPropertyFileSnitch — стандарт для production; топология берётся из cassandra-rackdc.properties.
    • PropertyFileSnitch, Ec2Snitch, GoogleCloudSnitch, AzureSnitch — для облачных и гибридных сред.
      Выбор влияет на корректность NetworkTopologyStrategy.
  • dynamic_snitch — включает динамический снитч — механизм, который снижает приоритет плохо отвечающих узлов при выборе реплик для чтения. Булево. По умолчанию: true. Рекомендуется оставлять включённым.

  • dynamic_snitch_update_interval_in_ms — интервал обновления «рейтинга» узлов динамического снитча. По умолчанию: 100.

  • dynamic_snitch_reset_interval_in_ms — интервал полного сброса рейтингов. По умолчанию: 600000 (10 минут).

  • dynamic_snitch_badness_threshold — порог, начиная с которого узел считается «плохим». По умолчанию: 0.1. Чем выше — тем более толерантна система к задержкам.

5. Параметры памяти и производительности

  • memtable_heap_space_in_mb, memtable_offheap_space_in_mb — ограничения на объём памяти, выделяемый под memtable (в куче и вне её соответственно). По умолчанию оба 0, что означает автоматический расчёт как 1/4 от общей памяти, выделенной под off-heap (если используется off-heap allocation). Ручная настройка требуется при тонкой оптимизации.

  • concurrent_reads, concurrent_writes, concurrent_counter_writes — количество потоков, выделяемых для фоновых операций чтения/записи. По умолчанию: 32, 32, 32. Увеличение может помочь при SSD и высоком IOPS, но не при HDD.

  • file_cache_size_in_mb — размер кэша для открытых файловых дескрипторов SSTable. По умолчанию: 512. При большом числе таблиц/файлов может быть увеличен.

  • memtable_flush_writers — количество потоков, выполняющих сброс memtable на диск (flush). По умолчанию: 2. При нескольких data_file_directories может быть увеличен до числа дисков.

  • compaction_throughput_mb_per_sec — ограничение скорости компактификации в МБ/с. По умолчанию: 16. При 0 — без ограничения. На production-системах часто ставят 16–64, чтобы не «забивать» диск.

  • stream_throughput_outbound_megabits_per_sec — ограничение скорости streaming (репликация, repair, bootstrap) в Мбит/с. По умолчанию: 200. Может быть увеличено до 1000 при 1 Гбит/с сети.

6. Параметры безопасности

  • authenticator — класс аутентификации.

    • AllowAllAuthenticator — отключена (по умолчанию).
    • PasswordAuthenticator — встроенная аутентификация по логину/паролю (хранятся в system_auth). Требует system_auth keyspace с NetworkTopologyStrategy.
    • Пользовательские реализации — через реализацию интерфейса IAuthenticator.
  • authorizer — класс авторизации (права доступа).

    • AllowAllAuthorizer — все операции разрешены (по умолчанию).
    • CassandraAuthorizer — управление правами через GRANT/REVOKE.
    • Также возможны кастомные реализации.
  • role_manager — управление ролями. По умолчанию: CassandraRoleManager.

  • client_encryption_options — параметры шифрования клиентских соединений.
    Подпараметры:

    • enabled: false → может быть true.
    • keystore, keystore_password, truststore, truststore_password — пути и пароли к Java KeyStore-файлам.
    • require_client_auth: false — требовать клиентский сертификат.
    • protocol: TLS, cipher_suites — список разрешённых шифров.
  • internode_encryption — шифрование трафика между узлами. Допустимые значения:

    • none — без шифрования (по умолчанию),
    • rack — только между стойками,
    • dc — только между датацентрами,
    • all — всегда.

7. Параметры отказоустойчивости и аварийного восстановления

  • hinted_handoff_enabled — включает hinted handoff. Булево. По умолчанию: true. Критично для временной отказоустойчивости.

  • max_hint_window_in_ms — максимальное окно (в миллисекундах), в течение которого hinted handoff накапливается для недоступного узла. По умолчанию: 10800000 (3 часа). После этого hinted handoff для этого узла прекращается — требуется nodetool repair.

  • hinted_handoff_throttle_in_kb — ограничение скорости отправки hinted handoff (в кБ/с). По умолчанию: 1024.

  • auto_snapshot — автоматически создаёт снапшот перед DROP TABLE или TRUNCATE. Булево. По умолчанию: true. Снапшоты хранятся в data/keyspace/table/snapshots/. Не отменяет необходимости регулярного бэкапа.

  • snapshot_before_compaction — создаёт снапшот перед major compaction. По умолчанию: false. Используется редко, только при отладке.

  • tombstone_warn_threshold, tombstone_failure_threshold — пороги для предупреждения и отказа при обнаружении большого числа tombstone'ов в одной партиции (риск «tombstone purge»). По умолчанию: 1000, 100000. Превышение failure_threshold вызывает TombstoneOverwhelmingException.


II. Свойства ключевых пространств (Keyspaces)

Ключевое пространство создаётся командой CREATE KEYSPACE и определяет логическую группу таблиц с единой политикой репликации и устойчивости к сбоям. У каждого keyspace есть два обязательных и один необязательный параметр.

1. replication — стратегия и параметры репликации

Это map-структура, передаваемая в CQL как строка JSON. Формат:
{'class': 'ReplicationStrategy', 'param1': 'value1', 'param2': 'value2', ...}

a) SimpleStrategy

Применяется только в одно-датацентровых (single-DC) окружениях. Не учитывает топологию.

  • class: 'SimpleStrategy'
  • replication_factor: целое число ≥ 1. Определяет, сколько копий каждой партиции данных хранится в кластере.
    1: без репликации (ненадёжно).
    2: выдерживает выход из строя одного узла.
    3: стандарт для production (выдерживает одновременный выход двух узлов, если они не владеют одинаковыми партициями).
    — Максимально допустимое значение ограничено числом узлов в кластере, но практически не рекомендуется выше 5.

⚠️ Нельзя использовать SimpleStrategy при endpoint_snitch, отличном от SimpleSnitch, — поведение неопределено.

b) NetworkTopologyStrategy

Единственная рекомендуемая стратегия для production. Позволяет задавать replication_factor отдельно для каждого датацентра.

  • class: 'NetworkTopologyStrategy'
  • '<dc_name>': целое число ≥ 0. Имя датацентра берётся из cassandra-rackdc.properties (dc=).
    Пример:
    CREATE KEYSPACE ks WITH replication = {
    'class': 'NetworkTopologyStrategy',
    'DC1': 3,
    'DC2': 2
    };
    Здесь в датацентре DC1 — 3 реплики, в DC2 — 2. В датацентрах, не указанных явно, репликация не производится (0).
    Значение 0 допустимо и означает отсутствие реплик в указанном DC.
    При добавлении нового DC в кластер требуется явно обновить keyspace:
    ALTER KEYSPACE ks WITH replication = {'class': 'NetworkTopologyStrategy', 'DC1':3, 'DC2':2, 'DC3':3};

Важно: репликация в дополнительный DC не происходит автоматически — только после ALTER KEYSPACE и nodetool rebuild -- <dc_name> на узлах целевого DC.

c) LocalStrategy

Специальная стратегия, используемая только для системного keyspace system_local. Не предназначена для пользовательских keyspace. Значение: 'LocalStrategy'.

2. durable_writes

Булев параметр: true или false. Указывает, должны ли операции записи в keyspace сопровождаться фиксацией в commit log.

  • По умолчанию: true.
  • При false: commit log не используется. Записи попадают только в memtable, а затем — в SSTable при flush.
  • Применение: только в случае, если данные временные, регенерируемые, и потеря при сбое допустима (например, кэш-таблицы).
  • Опасность: при аварийном завершении узла (например, power loss) данные, не успевшие сброситься на диск, теряются безвозвратно.
  • Может быть изменено через ALTER KEYSPACE.

⚠️ Значение durable_writes = false игнорируется, если commitlog_sync = periodic и commitlog_sync_period_in_ms > 0 — фактически durability обеспечивается только при commitlog_sync = batch.


III. Свойства таблиц (CQL CREATE TABLE / ALTER TABLE)

Таблица в Cassandra — упорядоченное множество строк, физически хранящееся в SSTable-файлах и разбитое на партиции по значению partition key. Свойства таблицы задаются в секции WITH.

1. Состав первичного ключа (PRIMARY KEY)

Не является «свойством» в секции WITH, но фундаментально определяет поведение таблицы.

  • PRIMARY KEY ((partition_key_part1, ...), clustering_column1, ...)
    (partition_key) — может быть составным (в скобках). Определяет, какие узлы отвечают за хранение данных (по хэшу от сериализованного значения).
    clustering_columns — порядок сортировки строк внутри партиции (по умолчанию — возрастание; можно указать ASC/DESC явно).
    — Количество clustering-столбцов определяет глубину вложенности строк.

Пример:

CREATE TABLE events (
user_id uuid,
event_time timestamp,
event_type text,
payload blob,
PRIMARY KEY (user_id, event_time, event_type)
);

Здесь:
user_id — partition key,
event_time, event_type — clustering columns (сортировка: сначала по времени, затем по типу — оба по возрастанию).
Одна партиция = все события одного пользователя.

2. Основные свойства таблицы (в секции WITH)

a) compaction

Настройка стратегии компактификации — процесса объединения SSTable-файлов для удаления дубликатов, устаревших версий и tombstone’ов.

Формат:
{'class': 'CompactionStrategy', 'option1': 'value1', ...}

i. SizeTieredCompactionStrategy (STCS)

Стандартная стратегия по умолчанию до версии 3.0.

  • class: 'SizeTieredCompactionStrategy'
  • bucket_high: 1.5 — верхняя граница соотношения размеров SSTable для объединения в bucket.
  • bucket_low: 0.5 — нижняя граница.
  • min_threshold: 4 — минимальное число SSTable в bucket для запуска compaction.
  • max_threshold: 32 — максимальное число SSTable, объединяемых за один проход.
  • min_sstable_size: 50 (МБ) — минимальный размер SSTable, учитываемый при группировке. Файлы меньше игнорируются.
  • tombstone_compaction_interval: 86400 (сек) — минимальное время с момента создания tombstone до попытки его удаления.
  • tombstone_threshold: 0.2 — доля tombstone’ов в SSTable, при которой разрешается compaction, даже если не набран min_threshold.

Применение: подходит для write-heavy нагрузок с равномерным распределением. Недостаток: высокий overhead по месту (до 2× объёма данных при активной записи).

ii. LeveledCompactionStrategy (LCS)

Оптимизирована для read-heavy и mixed workloads. Гарантирует, что любая партиция находится не более чем в N SSTable.

  • class: 'LeveledCompactionStrategy'
  • sstable_size_in_mb: 160 — целевой размер SSTable на уровне L1 и выше (L0 — без ограничения).
  • fanout_size: 10 — множитель роста объёма данных при переходе на следующий уровень (L1 = 10 × L0, L2 = 10 × L1 и т.д.).
  • level0_sstables_max_bytes: не настраивается напрямую.
  • tombstone_threshold: 0.2 — аналогично STCS, но используется реже, так как LCS эффективнее удаляет tombstone’ы.

Преимущества:
— Число чтений на одну партицию ≤ level_count (обычно 3–5).
— Меньше места при долгоживущих данных.
Недостатки:
— Высокий I/O при записи (каждая запись может вызвать чтение+запись на нескольких уровнях).
— Не подходит для очень высокой write throughput.

iii. TimeWindowCompactionStrategy (TWCS)

Оптимизирована для time-series данных, когда данные пишутся в «слоты времени» и редко обновляются/удаляются.

  • class: 'TimeWindowCompactionStrategy'
  • compaction_window_unit: 'DAYS' — единица окна (возможные: MINUTES, HOURS, DAYS).
  • compaction_window_size: 1 — размер окна в выбранных единицах.
  • expired_sstable_check_frequency_seconds: 600 — интервал проверки истёкших TTL-данных.

Принцип: все SSTable, созданные в одно временное окно, компактифицируются вместе (обычно STCS внутри окна), но между окнами — не компактифицируются. Через gc_grace_seconds + compaction_window_size старые окна можно удалять массово.

Требования:
— Записи должны упорядочены по времени (clustering column = timestamp).
— TTL или default_time_to_live желательны.
— Чтения должны быть в пределах одного или нескольких окон.

Пример для логов с TTL 7 дней:

WITH compaction = {
'class': 'TimeWindowCompactionStrategy',
'compaction_window_unit': 'HOURS',
'compaction_window_size': '6'
}
AND default_time_to_live = 604800;

b) compression

Настройка сжатия SSTable на диске.

Формат:
{'class': 'CompressionClass', 'option1': 'value1', ...}

i. LZ4Compressor

Стандарт по умолчанию (начиная с 3.0). Быстрое сжатие и распаковка, умеренный коэффициент (~2–3×).

  • class: 'LZ4Compressor'
  • chunk_length_in_kb: 16 — размер блока, на который разбивается SSTable перед сжатием. Чем больше — выше коэффициент, но выше overhead при чтении. Допустимые: 4, 8, 16, 32, 64.
  • crc_check_chance: 1.0 — вероятность проверки CRC32 контрольной суммы при чтении блока (защита от bit rot). Может быть 0.0 для отключения.
ii. SnappyCompressor

Более старый компрессор, чуть медленнее LZ4, но совместим со старыми версиями.

  • class: 'SnappyCompressor'
  • chunk_length_in_kb: 16 (аналогично)
  • crc_check_chance: 1.0
iii. DeflateCompressor

Высокий коэффициент сжатия (~4–5×), но высокая CPU-нагрузка. Редко используется.

  • class: 'DeflateCompressor'
  • chunk_length_in_kb: 16
  • crc_check_chance: 1.0
iv. Отключение сжатия
  • class: 'DisabledCompressor'
  • Никаких дополнительных параметров.

Рекомендация: LZ4 для большинства случаев. Отключать сжатие — только если данные уже сжаты (например, JPEG, PNG, gzip’ed JSON), иначе waste CPU.

c) caching

Управление кэшированием на уровне узла.

  • keys: 'ALL' или 'NONE' — кэширование partition key (key cache). По умолчанию: 'ALL'.
  • rows_per_partition: целое число или 'ALL'/'NONE' — кэширование строк (row cache). По умолчанию: 'NONE'.
    'ALL': все строки партиции (опасно при больших партициях).
    '10': первые 10 строк (по порядку clustering).
    — Значение применяется на узел, не на запрос.

⚠️ Row cache хранится в off-heap памяти. При больших партициях может вызвать OOM.

d) default_time_to_live

Целое число — TTL по умолчанию для всех вставляемых строк, если не указан явно в запросе. Единица — секунды.

  • По умолчанию: 0 (бессрочно).
  • Пример: 2592000 = 30 дней.
  • При вставке с USING TTL 3600 — перекрывается.
  • Истёкшие данные помечаются tombstone’ом при следующей компактификации (если gc_grace_seconds уже прошло).

e) gc_grace_seconds

Целое число — минимальное время (в секундах), в течение которого tombstone сохраняется перед удалением при compaction.

  • По умолчанию: 864000 (10 дней).
  • Должно быть не меньше, чем интервал между nodetool repair (обычно 7–10 дней).
  • Слишком маленькое значение → риск resurrection (воскрешения удалённых данных при отставании узла).
  • Слишком большое → рост размера данных и замедление compaction.

f) speculative_retry

Политика speculative retry — отправка дублирующего запроса на другой узел-реплику при задержке.

  • 'NONE': отключено (по умолчанию в ранних версиях).
  • '99.0PERCENTILE': отправить дубль, если ответ не получен за 99-й перцентиль задержки (собирается статистика).
  • '50.0PERCENTILE': аналогично, но на 50-м перцентиле (агрессивнее).
  • 'ALWAYS': всегда отправлять два запроса (на два узла), брать первый ответ. Увеличивает нагрузку, но минимизирует tail latency.
  • 'Xms': константный таймаут (например, '200ms').

g) read_repair_chance, dclocal_read_repair_chance

Вероятность фонового read repair (устаревшие параметры, начиная с 4.0 ведут себя иначе):

  • read_repair_chance: 0.0 — глобальный read repair (устарел, не рекомендуется).
  • dclocal_read_repair_chance: 0.1 по умолчанию в 3.x, но начиная с Cassandra 4.0 оба параметра игнорируются. Read repair теперь происходит только при уровне согласованности QUORUM/ALL и только в рамках локального DC (если используется LOCAL_QUORUM).

Рекомендация: всегда ставить оба в 0.0, полагаться на регулярный nodetool repair.

h) bloom_filter_fp_chance

Допустимая доля ложных срабатываний (false positive rate) фильтра Блума.

  • По умолчанию: 0.01 (1%).
  • Диапазон: от 0.0001 до 0.1.
  • Чем меньше — тем точнее фильтр, но тем больше памяти он занимает (и выше I/O при чтении).
  • 0.1 — 10% ложных срабатываний, минимальный размер.
  • 0.0001 — 0.01% ложных, но размер фильтра растёт линейно.
  • Фильтр хранится в off-heap и используется для отсечения SSTable, не содержащих нужного partition key.

i) memtable_flush_period_in_ms

Интервал (в мс), через который memtable принудительно сбрасывается на диск, даже если не заполнена.

  • По умолчанию: 0 (отключено).
  • Пример: 3600000 = 1 час.
  • Применение: таблицы с низкой write throughput, но требующие гарантии записи на диск через фиксированное время (например, аудит).
  • Влияет только на ту таблицу, где установлено.

j) cdc — Change Data Capture

  • true/false — включает буферизацию изменений в отдельный CDC-директорий (cdc_raw_directory).
  • По умолчанию: false.
  • Требует мониторинга и обработки внешней системой (например, Kafka Connect).
  • При переполнении (cdc_free_space_in_mb) Cassandra блокирует запись в таблицу.

k) comment

Произвольная строка для документирования таблицы. Не влияет на поведение.

  • По умолчанию: ''.
  • Пример: 'User event log, TTL=7 days, partitioned by user_id'.

l) max_index_interval, min_index_interval

Детали внутренней индексации SSTable (sparse index):

  • min_index_interval: 2 — минимальное число строк между записями в индексе (чем меньше — точнее, но больше индекс).
  • max_index_interval: 2048 — максимальное.
  • При поиске Cassandra интерполирует позицию по индексу, затем сканирует SSTable от найденной точки.
  • Редко меняется; изменение требует перезаписи SSTable (через nodetool upgradesstables).

m) index_interval (устарело)

Заменено на min_index_interval в 3.0+. Игнорируется.


IV. Свойства и параметры CQL-запросов

CQL (Cassandra Query Language) имитирует SQL-подобный синтаксис, но семантически сильно ограничен. Большинство расширенных возможностей реализовано через необязательные модификаторы, задаваемые в запросе или на уровне сессии.

1. Уровни согласованности (Consistency Levels)

Указываются перед выполнением запроса:

CONSISTENCY <level>;

Применяются к последующим запросам в сессии cqlsh, либо задаются на уровне драйвера (например, Statement.setConsistencyLevel() в Java Driver).

a) Для операций чтения и записи

  • ANY — только для записи. Запрос считается успешным, если хотя бы один узел принял hint (даже если целевой узел недоступен). Риск потери данных при одновременном отказе hint-узла и координатора.

  • ONE — один узел-реплика должен ответить (для чтения) или подтвердить запись (для записи). Минимальная задержка, минимальная отказоустойчивость.

  • TWO, THREE — 2 или 3 реплики соответственно. Используются редко, только в кластерах с RF ≥ 3.

  • QUORUM — большинство реплик: ⌊RF/2⌋ + 1. Стандарт для большинства операций. Обеспечивает линейную согласованность при RF = 3 (QUORUM = 22 + 2 > 3).

  • ALL — все реплики должны ответить. Максимальная согласованность, минимальная доступность. Рекомендуется только для критичных изменений схемы.

  • LOCAL_ONE, LOCAL_QUORUM — аналоги ONE и QUORUM, но ограничены локальным датацентром (определяется по NetworkTopologyStrategy и endpoint_snitch). Рекомендуются для multi-DC production.

  • EACH_QUORUM — только для записи. Требует QUORUM в каждом датацентре, где есть реплики. Высокая задержка, редко используется.

b) Для условных операций (Lightweight Transactions, LWT)

Используются при IF-условиях (INSERT ... IF NOT EXISTS, UPDATE ... IF condition). Работают на основе алгоритма Paxos, требуют двух фаз.

  • SERIAL — для чтения в рамках LWT. Гарантирует чтение последней зафиксированной версии перед началом Paxos-операции. По умолчанию для SELECT ... FOR UPDATE.

  • LOCAL_SERIAL — то же, но только в локальном DC.

⚠️ LWT медленнее обычных операций в 10–100 раз. Не использовать в hot path.

2. Явное управление временными метками и временем жизни

a) USING TIMESTAMP <microseconds>

Задаёт временную метку операции вручную (в микросекундах Unix epoch).

  • Применяется к INSERT, UPDATE, DELETE.
  • Пример:
    INSERT INTO events (id, ts, value) VALUES (1, '2025-11-21', 42)
    USING TIMESTAMP 1732123200000000;
  • Перезаписывает значение только если указанная метка новее, чем у существующего.
  • Используется для устранения конфликтов при репликации, backfill’е данных, синхронизации с внешними системами.

b) USING TTL <seconds>

Задаёт время жизни конкретной операции (перекрывает default_time_to_live таблицы).

  • Применяется к INSERT, UPDATE, DELETE (для tombstone).
  • TTL 0 эквивалентен бессрочному значению (но не отменяет ранее установленный TTL).
  • TTL не может быть отрицательным.

c) WRITETIME(column_name)

Скалярная функция в SELECT, возвращает временную метку последней записи для указанного столбца (в микросекундах).

  • Только для существующих столбцов.
  • Для NULL — возвращает NULL.
  • Используется для аудита, отладки конфликтов версий.

d) TTL(column_name)

Скалярная функция, возвращает оставшееся время жизни столбца в секундах.

  • Для данных без TTL — возвращает NULL.
  • Уменьшается динамически со временем.

3. Условные операции (Lightweight Transactions)

a) IF NOT EXISTSINSERT)

Гарантирует, что запись будет вставлена только если партиция (или строка) не существует.

  • Атомарна.
  • Пример:
    INSERT INTO users (id, name) VALUES (uuid(), 'Alex') IF NOT EXISTS;
  • Возвращает [applied] true/false + текущие значения при false.

b) IF <condition>UPDATE, DELETE, INSERT)

Проверяет условие перед применением.

  • Условия: =, <, >, <=, >=, IN.
  • Можно проверять несколько столбцов:
    UPDATE accounts SET balance = balance - 100 
    WHERE user_id = 1
    IF balance >= 100 AND version = 5;
  • При неудаче возвращает текущие значения столбцов из условия.

⚠️ LWT не масштабируются линейно. Один partition key — один сериализационный контекст. При высокой конкурентности по одному ключу — contention.

4. JSON-поддержка

a) INSERT INTO ... JSON '<string>'

Вставка из строки JSON.

  • Имена полей должны точно совпадать с именами столбцов.
  • Partition/clustering ключи обязательны.
  • Пример:
    INSERT INTO events JSON '{"user_id": "a0eebc...", "event_time": "2025-11-21T10:00:00Z", "type": "login"}';
  • Не поддерживает USING, TTL, TIMESTAMP внутри JSON — задаются снаружи.

b) SELECT JSON ...

Возвращает результат в виде одной колонки '[json]' с JSON-строкой.

  • Включает все запрошенные столбцы.
  • NULL значения опускаются.
  • Пример:
    SELECT JSON user_id, event_time FROM events WHERE user_id = ?;

5. Ограничения выборки

a) LIMIT <n>

Ограничивает общее число строк в результате.

  • По умолчанию: 10000cqlsh).
  • Может быть задано выше, но с осторожностью: Cassandra читает данные с нескольких узлов, и LIMIT применяется после объединения.

b) PER PARTITION LIMIT <n>

Ограничивает число строк внутри каждой партиции.

  • Работает только при фиксированном partition key в WHERE.
  • Пример:
    SELECT * FROM events 
    WHERE user_id = ?
    PER PARTITION LIMIT 100;
  • Эффективен: Cassandra прекращает чтение из SSTable после n строк в партиции.

6. Работа с коллекциями

a) UPDATE ... SET list = list + [value]

Добавление в список (append).

  • list = [value] + list — prepend.
  • Для set и map — аналогично.

b) UPDATE ... SET map[key] = value

Частичное обновление map (только указанный ключ).

c) TTL для элементов коллекции

Можно задать TTL отдельному элементу (только для map и set):

UPDATE events 
SET metadata['temp_flag'] = '1'
USING TTL 3600
WHERE user_id = ? AND event_time = ?;

⚠️ TTL коллекции как целого не работает напрямую — только через полное перезаписывание с USING TTL.


V. Вторичные индексы (Secondary Indexes)

Создаются командой CREATE INDEX. Не являются полноценной заменой primary key — используются только для фильтрации, не для выбора партиции.

1. Типы индексов

a) CREATE INDEX ON table (column)

Стандартный индекс по одному столбцу.

  • Поддерживает: text, ascii, varchar, int, bigint, uuid, inet, boolean, date, timestamp.
  • Не поддерживает: blob, counter, frozen<udt>, collection (если не указан ENTRIES или KEYS).
  • Хранится локально на каждом узле (не распределяется).
  • Применяется только если в WHERE есть:
    • Точный = для indexed column,
    • И partition key задан полностью.

b) CREATE INDEX ON table (ENTRIES(map_column))

Индекс по парам key → value map.

  • Позволяет фильтровать по значению: WHERE map_column['k'] = 'v'.
  • Не позволяет фильтровать только по ключу без значения.

c) CREATE INDEX ON table (KEYS(set_or_map_column))

Индекс по ключам коллекции.

  • Для set: позволяет WHERE column CONTAINS key.
  • Для map: WHERE column CONTAINS KEY key.

d) CREATE INDEX ON table (FULL(column)) (начиная с 4.0)

Индекс по замороженному UDT или коллекции целиком.

  • Требует frozen<type>.
  • Пример:
    CREATE TYPE address (city text, street text);
    CREATE TABLE users (id uuid, home frozen<address>);
    CREATE INDEX ON users (FULL(home));
    SELECT * FROM users WHERE home = {city: 'Ufa', street: 'Lenina'};

e) SASI (Stubborn Apache Secondary Index) — устарел

SASI (CREATE CUSTOM INDEX ... USING 'org.apache.cassandra.index.sasi.SASIIndex') предоставлял LIKE, range-поиск, но:

  • Удалён в Cassandra 4.1.
  • Не рекомендовался к production даже в 3.x.

2. Ограничения и рекомендации

  • Не используйте индексы для high-cardinality столбцов (например, uuid) — эффективность низкая.
  • Не используйте, если можно перестроить модель данных под primary key.
  • Индекс создаёт накладные расходы на запись (локальное обновление индекса на каждом узле).
  • При SELECT без partition key — full cluster scan (запрещено по умолчанию; требует ALLOW FILTERING).

3. Управление индексами

  • DROP INDEX keyspace.index_name;
  • ALTER TABLE ... DROP INDEX index_name; — некорректно, только DROP INDEX.
  • Состояние: nodetool cfstats keyspace.tableSecondary indexes.

VI. Материализованные представления (Materialized Views) — устаревшая функция

Введены в 3.0, но официально deprecated в 4.0 и удалены в 5.0. Привожу для полноты, так как ещё встречаются в legacy-системах.

1. Создание

CREATE MATERIALIZED VIEW view_name AS
SELECT column1, column2, ...
FROM base_table
WHERE column IS NOT NULL
PRIMARY KEY ((pk_part), ck_part);

2. Ограничения

  • Базовая таблица должна иметь только один clustering column в условии WHERE IS NOT NULL.
  • Во view должен входить полный partition key базовой таблицы.
  • Не поддерживает TTL, LWT, коллекции (кроме frozen).
  • Задержка обновления — до нескольких секунд.
  • При высокой нагрузке — высокая нагрузка на coordinator.

3. Альтернативы

  • Дублирование данных вручную (application-managed denormalization).
  • Использование SELECT ... JSON + обработка на клиенте.
  • Выделенные таблицы под нужный access pattern.

Рекомендация: не использовать в новых проектах.


VII. Параметры клиентских драйверов (на примере DataStax Java Driver 4.x)

Хотя драйверы различаются, большинство параметров унифицированы.

1. Connection Pooling

  • coreConnectionsPerHost / maxConnectionsPerHost — число соединений на узел в пуле.
    — По умолчанию: 1 (local DC), 1 (remote DC).
    — Для высокой нагрузки: 2–8 (local), 1 (remote).
  • maxRequestsPerConnection — максимальное число одновременных запросов на одно соединение (HTTP/2-подобно). По умолчанию: 1024.

2. Политики повторных попыток (RetryPolicy)

  • DefaultRetryPolicy — retry только при UNAVAILABLE, READ_TIMEOUT, WRITE_TIMEOUT с определёнными условиями.
  • FallthroughRetryPolicy — не повторять, передавать исключение выше.
  • ConservativeRetryPolicy — retry только при IS_BOOTSTRAPPING или OVERLOADED.
  • Кастомные политики — реализация интерфейса RetryPolicy.

3. Speculative Execution

Отправка дублирующих запросов при задержке.

  • speculativeExecutionPolicy:
    ConstantSpeculativeExecutionPolicy(delay_ms, max_executions) — например, (200, 2): дубль через 200 мс, максимум 2 попытки.
    NoSpeculativeExecutionPolicy — отключено.

4. Load Balancing и Discovery

  • DCAwareLoadBalancingPolicy — предпочитает узлы локального DC.
  • TokenAwarePolicy — оборачивает другую политику, добавляя предпочтение репликам (минимизирует network hops).
  • NodeDiscovery — автоматическое обнаружение узлов через Gossip (включено по умолчанию).

5. Аутентификация и SSL

  • PlainTextAuthProvider(username, password) — для PasswordAuthenticator.
  • ProgrammaticSslContextFactory — для TLS.
  • withLocalDatacenter() — обязательно при multi-DC.

VIII. JMX-интерфейс Cassandra

Cassandra предоставляет полный набор управляемых и измеряемых параметров через Java Management Extensions (JMX). Доступ осуществляется по умолчанию на порту 7199 (настраивается через cassandra-env.shJMX_PORT). Все атрибуты и операции доступны через jconsole, jvisualvm, nodetool (который сам является JMX-клиентом) или Prometheus JMX Exporter.

1. Иерархия доменов JMX

Основные домены:

  • org.apache.cassandra.db — состояние таблиц, memtable, SSTable, кэшей.
  • org.apache.cassandra.metrics — метрики (таймеры, счётчики, гистограммы).
  • org.apache.cassandra.net — сетевые метрики (отправка/приём, streaming).
  • org.apache.cassandra.internal — фоновые потоки (compaction, memtable flush).
  • org.apache.cassandra.request — обработка запросов (read/write stages).
  • org.apache.cassandra.compaction — состояние и управление компактификацией.

2. Ключевые атрибуты

a) org.apache.cassandra.db:type=Tables,keyspace=<ks>,table=<table>

  • MemtableLiveDataSize — объём «живых» данных в memtable (байты, off-heap).
  • MemtableColumnsCount, MemtableRowsCount — число столбцов и строк в memtable.
  • LiveSSTableCount — количество активных SSTable.
  • TotalDiskSpaceUsed — общий размер SSTable на диске (без учёта сжатия).
  • SnapshotsSize — размер всех снапшотов.
  • KeyCacheHitRate, RowCacheHitRate — эффективность кэшей (float от 0.0 до 1.0).
  • CompressionRatio — среднее отношение несжатого/сжатого размера (например, 0.35 → 2.86× сжатие).

b) org.apache.cassandra.metrics:type=Table,keyspace=<ks>,scope=<table>,name=<metric>

Метрики в формате Dropwizard Metrics. Типы:

  • Counter — накапливаемые значения (например, WriteTotalLatency).
  • Histogram — распределение (например, WriteLatency50thPercentile, 99thPercentile, Mean).
  • Gauge — мгновенные значения (например, PendingCompactions).

Основные метрики по категориям:

Чтение
  • ReadLatency — задержка локального чтения (не end-to-end).
  • RangeSliceLatency — задержка для SELECT без partition key (с ALLOW FILTERING).
  • SpeculativeRetries — счётчик запущенных speculative-запросов.
Запись
  • WriteLatency — задержка локальной записи (до commit log + memtable).
  • PendingWrites — очередь записей в stage-очереди (должна быть близка к 0).
  • DroppedMutations — мутации, отброшенные из-за переполнения очереди (тревожный сигнал).
Компактификация
  • PendingCompactions — количество SSTable, ожидающих компактификации.
  • BytesCompacted — суммарный объём данных, обработанных компактификацией (с момента старта).
  • CompactionHistory — табличное представление завершённых компактификаций (можно экспортировать).
Кэши
  • KeyCacheHitRate, RowCacheHitRate — уже упомянуты.
  • CacheCapacity — объём памяти под кэш (в строках или байтах).
  • CacheSize — текущее использование.
Gossip и отказоустойчивость
  • FailureDetectorDownEndpointCount — число узлов, помеченных как down.
  • HintedHandoffHintsCreated, HintsSent, HintsTimedOut — статистика hinted handoff.

3. Полезные операции (invoke-методы)

  • forceKeyspaceFlush(<ks>) — принудительный flush всех таблиц keyspace на диск.
  • forceKeyspaceCompaction(<ks>, <table1>, <table2>, ...) — major compaction (не рекомендуется в production).
  • truncate(<ks>, <table>) — безопасный TRUNCATE (с снапшотом, если auto_snapshot=true).
  • repairAsync(<ks>, <table>) — запуск repair в фоне, возвращает ID задачи.
  • setCacheCapacity(<type>, <capacity>) — динамическое изменение размера кэша (KeyCache, RowCache).
  • stopDaemon() — graceful shutdown узла.

⚠️ Прямые вызовы JMX-операций требуют понимания последствий. Предпочтительно использовать nodetool.


IX. Утилита nodetool

Командная утилита для администрирования и мониторинга Cassandra. Подключается к локальному или удалённому узлу через JMX.

1. Диагностика состояния кластера

  • nodetool status — краткий статус всех узлов:
    UN — Up, Normal.
    DN — Down, Normal (недоступен).
    UJ — Up, Joining (в процессе bootstrap).
    UL — Up, Leaving (в процессе decommission).
    UM — Up, Moving (перемещение токенов).
    Вывод включает: load, owns (%), host ID, rack/DC.

  • nodetool info — информация об узле: uptime, heap usage, data size, cache stats, commit log size.

  • nodetool ring — детальное представление токенов и ownership (устарело в пользу status, но даёт точные границы партиций).

2. Управление данными

  • nodetool flush <ks> <table> — сброс memtable на диск → SSTable. Безопасен, минимальная нагрузка.

  • nodetool compact <ks> <table> — запуск major compaction (все SSTable → один). Использовать только в крайних случаях (например, удаление всех данных через TTL + gc_grace_seconds истёк). Вызывает high I/O и может нарушить баланс.

  • nodetool cleanup <ks> — удаление данных, не принадлежащих узлу (после изменения replication_factor или num_tokens). Работает только локально.

  • nodetool clearsnapshot <ks> — удаление всех снапшотов. Безопасно, если бэкап сделан.

  • nodetool refresh <ks> <table> — загрузка SSTable из staging-директории (для sstableloader).

3. Репарация и согласованность

  • nodetool repair — запуск repair для всех таблиц (по умолчанию последовательно).
    --partitioner-range — repair только «свои» токены (быстрее, требует запуска на всех узлах).
    --pr (устарело, заменено --partitioner-range).
    --full — full repair (не incremental), сравнивает все данные, а не только merkle tree различия.
    --in-local-dc — ограничение repair локальным DC.
    --start-token / --end-token — точечный repair по диапазону.

  • nodetool verify <ks> <table> — проверка целостности SSTable (CRC32, index consistency). Не влияет на данные.

4. Мониторинг и профилирование

  • nodetool tablestats <ks>.<table> — подробная статистика: SSTable count, space used, read/write latency percentiles, cache hit rates, speculative retries.

  • nodetool cfhistograms <ks> <table> — гистограммы:
    SSTables per read — сколько SSTable читается на один запрос (цель: < 3–5).
    Write latency, Read latency — распределение в микросекундах.
    Partition size, Cell count — выявление «толстых» партиций.

  • nodetool toppartitions <duration_ms> — профилирование «горячих» partition key в реальном времени.
    — Выводит top-N самых нагруженных ключей по чтению/записи.
    — Требует dynamic_snitch: true.
    — Полезен при contention и hot partition.

  • nodetool settraceprobability <probability> — включение tracing для случайных запросов (например, 0.01 = 1%). Логи пишутся в system_traces.

  • nodetool gettrace <session_id> — получение полного трейса по ID.

5. Управление hinted handoff и repair

  • nodetool statushandoff — статус hinted handoff (включён/выключён).
  • nodetool disablehandoff, enablehandoff — временное отключение (например, при массовом repair).
  • nodetool pruneschema — удаление устаревших миграций схемы (при ошибке SchemaDisagreement).

X. Метрики и мониторинг в production

Для построения надёжной системы требуется интеграция с системами сбора метрик.

1. Prometheus + JMX Exporter

  • Используется jmx_exporter (агент от Prometheus) с конфигурацией, фильтрующей только нужные MBean’ы.
  • Рекомендуемые метрики для алертинга:
    org_apache_cassandra_metrics_table_write_total_latency_count — рост скорости записи.
    org_apache_cassandra_metrics_table_read_latency_99thpercentile — tail latency.
    org_apache_cassandra_metrics_cache_key_cache_hit_rate_value — падение ниже 0.95.
    org_apache_cassandra_net_dropped_messages_total — любое значение > 0.
    org_apache_cassandra_compaction_pending_tasks_value — рост выше 100 (признак нехватки I/O).

2. Grafana Dashboards

  • Официальный dashboard от DataStax: Cassandra Overview.
  • Ключевые панели:
    Node Status & Load — uptime, heap, load.
    Read/Write Latency — 50/95/99 перцентили.
    Compaction & Flush — pending tasks, bytes compacted.
    Cache Efficiency — hit rate.
    Dropped Messages — по типам (READ_REPAIR, MUTATION, HINT).

3. Логирование

  • system.log — основной лог (INFO по умолчанию). Уровень меняется в logback.xml.
  • debug.log — расширенный (включает gossip, compaction details).
  • gc.log — лог сборщика мусора (обязателен для диагностики pause’ов).
  • audit.log — при включённом аудите (cassandra.yamlaudit_logging_options).

Рекомендация: отправлять system.log в ELK/Graylog с парсингом структуры (например, через cassandra-logback-encoder).


XI. Типовые конфигурации под сценарии

1. Time-Series (логи, метрики, IoT)

Модель данных:

  • Partition key: (metric_name, bucket_time) — например, ('cpu_usage', '2025-11-21').
  • Clustering: timestamp DESC, host_id.
  • default_time_to_live = 2592000 (30 дней).

Настройки таблицы:

CREATE TABLE metrics (
name text,
day date,
ts timestamp,
host uuid,
value double,
PRIMARY KEY ((name, day), ts, host)
)
WITH CLUSTERING ORDER BY (ts DESC)
AND compaction = {
'class': 'TimeWindowCompactionStrategy',
'compaction_window_unit': 'DAYS',
'compaction_window_size': '1'
}
AND default_time_to_live = 2592000
AND gc_grace_seconds = 86400;

Параметры cassandra.yaml:

  • concurrent_compactors = 4 (на SSD).
  • compaction_throughput_mb_per_sec = 64.
  • memtable_flush_writers = 4.

2. Event Sourcing / Audit Log

Требования: гарантированная запись, упорядоченность, долгое хранение.

Модель:

  • Partition key: aggregate_id (например, order_uuid).
  • Clustering: event_version ASC (sequence number).
  • event_type, payload, created_at.

Настройки:

  • gc_grace_seconds = 2592000 (30 дней) — чтобы repair успевал.
  • speculative_retry = 'NONE' — не нарушать порядок.
  • durable_writes = true (обязательно).
  • commitlog_sync = batch (максимальная durability, но ниже throughput).

3. Высокочастотная запись (ingestion, telemetry)

Требования: > 100K writes/с на кластер.

Оптимизации:

  • num_tokens = 128 (баланс между балансировкой и overhead’ом).
  • commitlog_directory на отдельном NVMe.
  • memtable_heap_space_in_mb = 2048, memtable_offheap_space_in_mb = 2048.
  • concurrent_writes = 128.
  • compaction_throughput_mb_per_sec = 0 (без ограничения).
  • Таблица: compaction = {'class': 'SizeTieredCompactionStrategy', 'min_threshold': 6}.

Избегать:

  • LWT, secondary indexes, materialized views.
  • Операций DELETE (использовать TTL).

4. Кэширующий слой (вместо Redis для read-heavy)

Модель:

  • Partition key: cache_key (хэш запроса).
  • Single row: value, expires_at.
  • TTL задаётся явно в INSERT.

Настройки:

  • caching = {'keys': 'ALL', 'rows_per_partition': 'ALL'}.
  • bloom_filter_fp_chance = 0.1 (меньше памяти под фильтр).
  • read_repair_chance = 0.0, dclocal_read_repair_chance = 0.0.
  • speculative_retry = 'ALWAYS' — минимизация latency.

Узел:

  • Выделенный Cassandra-кластер с большим объёмом off-heap (row cache).
  • memtable_flush_period_in_ms = 300000 (5 мин) — чтобы данные дольше жили в памяти.