ru
Feedback
Cassandra & Beyond

Cassandra & Beyond

Открыть в Telegram

Sharing of interesting links, thoughts, insights about Apache Cassandra and related technical topics (such as Java, perf, computer science)

Больше
228
Подписчики
Нет данных24 часа
+27 дней
+330 день
Архив постов
Рассказал про использование памяти в Cassandra на Apache Cassandra Contributor Meeting | June 10th, 2026 https://www.youtube.com/watch?v=8Sw_sx_dJEI

Сделал сегодня доклад на JPoint 2026: https://jpoint.ru/talks/0e74f6b4f499426ea41d25a98c567607/ Рассказал о ряде оптимизаций в java коде, используя Cassandra как пример. Надеюсь, в этом году выйдет 6.0 версия, где эти и многие другие perf улучшения были реализованы.

Automated Repair Inside Cassandra (CEP-37) забекпортили в 5.0.x CEP-37 - это встроенная логика оркестрации cassandra repair активности, которая работает внутри самой Cassandra и не требует внешнего оркестратора, такого как Cassandra Reaper. Некоторое время была предложена разработчиками из Uber и реализована в trunk, теперь доступна и в 5.0.x ветке. 5.0.8 релиз, который включает её, на подходе. Детали по активации этой логике в 5.0.x есть в NEWS обновлении: https://github.com/apache/cassandra/commit/9500eb129bd61b2eaec78df3b9a7a5ebfca91c92#diff-95c20d744db732cdbca24c3e0406c10005ecf7fe8b5719c2fdf2b8af3fcedc79 Доклад про auto-repair: https://www.youtube.com/watch?v=wnLcpApF1eo - https://issues.apache.org/jira/browse/CASSANDRA-21138 - https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-37%3A+Apache+Cassandra+Unified+Repair+Solution

Visualizing Cassandra SSTable Lifecycles Немного вайбкодинга с моей стороны 😁 Периодически в Apache Cassandra возникает необ
Visualizing Cassandra SSTable Lifecycles Немного вайбкодинга с моей стороны 😁 Периодически в Apache Cassandra возникает необходимость разобраться, что происходит с SSTable-файлами — например, при скачках использования места на диске. Основной источник информации здесь (помимо метрик) — debug.log, но такой анализ обычно сводится к просмотру множества строк логов, что неудобно. Я сделал bash скрипт, который превращает их в интерактивную HTML-временную шкалу, где видно, когда SSTable создаются, объединяются и удаляются. Текущая версия скрипта выложена тут, https://github.com/netudima/cassandra-tools Реализацию в основном писал Claude Code, я лишь давал ему требования и обратную связь. Скрипт (sstable_timeline.sh) парсит debug-логи и генерирует самодостаточный HTML с canvas-визуализацией. Каждый SSTable — горизонтальная полоса: зелёный для flush, синий для компакций, серый для файлов, существовавших до начала логов. Полосы отсортированы по размеру, поэтому распределение видно сразу.

Cassandra 4.0.20/4.1.11/5.0.7 released https://github.com/apache/cassandra/blob/cassandra-4.0.20/CHANGES.txt https://github.com/apache/cassandra/blob/cassandra-4.1.11/CHANGES.txt https://github.com/apache/cassandra/blob/cassandra-5.0.7/CHANGES.txt мой вклад: - Dynamically skip sharding L0 when SAI Vector index present (CASSANDRA-19661) - ревью, был сломан сброс SAI vector индекса на диск, в случае UCS, поскольку UCS может сбрасывать данные из memtable в более чем одну SSTable, а логика SAI vector индекса к этому пока не готова - Switch lz4-java to at.yawk.lz4 version due to CVE (CASSANDRA-21052) - ревью, security обновление 3rd party зависимости - Fix cleanup of old incremental repair sessions in case of owned token range changes or a table deleting (CASSANDRA-20877) - исправление, данные не очищались в одной из служебных таблиц, в случае изменения топологии кластера, что в итоге может привести к увеличению потребления памяти и замедлению старта (данные из этой таблицы читаются при старте) Fix memory leak in BufferPoolAllocator when a capacity needs to be extended (CASSANDRA-20753) - исправление, буфер не возращался в пул, в случае когда netty буфер необходимо было увеличивать размере рамках обработки сетевого запроса

Removal of Sensitive Data from JFR and Heap Dumps Не стоит забывать, что диагностические данные могут содержать чувствительную информацию — например, пароли. Если текстовые логи относительно легко отредактировать и удалить из них такие данные, то с бинарными форматами всё значительно сложнее. JFR-файлы и heap dump’ы могут хранить большое количество информации, и точечное удаление информации из них — нетривиальная задача. Недавно Johannes Bechberger опубликовал две утилиты, которые помогают удалять чувствительные данные из: - JFR-файлов (Java Flight Recorder) - Java heap dump’ов (HPROF) Подробности: - https://mostlynerdless.de/blog/2026/02/24/redacting-data-from-heap-dumps-via-hprof-redact/ - https://mostlynerdless.de/blog/2026/02/13/redacting-sensitive-data-from-java-flight-recorder-files/ Эти утилиты могут быть полезными для тех, кто делится диагностикой с внешними командами, но хочет минимизировать риски утечки данных.

Reduce Memory Allocation During Transformation of BatchStatement to Mutation Продолжаю выжимать дополнительную пропускную способность из CPU-intensive сценария локальной записи в Cassandra. На этот раз я сосредоточился на логике координации, отвечающей за преобразование batch CQL-запроса во внутреннее представление - Mutation. Изменения, внесённые в https://issues.apache.org/jira/browse/CASSANDRA-21141, позволяют сократить выделение памяти в Java heap на 20% и увеличить пропускную способность на 7% в типичных сценариях использования. Некоторые из этих оптимизаций также улучшают производительность одиночных (не batch) операций записи. В тикете реализовано несколько оптимизаций. Две из наиболее интересных, на мой взгляд: 1) (Высокоуровневая) batch-запросы часто используются для записи большого количества однородных строк с одним и тем же запросом и одним и тем же набором изменяемых колонок — различаются только значения. В таких случаях можно избежать затрат CPU и лишних аллокаций, связанных с агрегацией итогового набора изменённых колонок. Распознавая этот паттерн, мы уменьшаем избыточную работу и количество ненужных аллокаций. 2) (Низкоуровневая) Мы вычисляем Murmur3-хеш для partition key. Результат представляет собой 128-битное значение, и поскольку в Java нет примитивного типа для 128-битных чисел, приходится выделять массив long[2] для возврата результата. В некоторых случаях JIT-компилятор Java может устранить такие аллокации, если они ограничены локальной областью видимости (благодаря escape analysis). Однако для этого должны выполняться несколько условий: соответствующие методы должны быть заинлайнены, а объект не должен «утекать» за пределы области компиляции. К сожалению, метод вычисления Murmur3 слишком велик, чтобы по умолчанию быть заинлайненным, и простого способа уменьшить его размер нет. Однако поведение JIT можно скорректировать для конкретных методов с помощью compiler directive. После добавления небольшой подсказки для JIT удалось добиться необходимого инлайнинга. Это помогло и JIT компилятор смог убрать эту аллокацию. Информации об устранении аллокаций JIT-ом не так уж много; вот несколько полезных ссылок: https://shipilev.net/jvm/anatomy-quarks/18-scalar-replacement/ https://www.youtube.com/watch?v=p1MhRBYS-k0 https://jpbempel.github.io/2020/08/02/when-escape-analysis-fails-you.html https://www.youtube.com/watch?v=K6c3W6vhQOA

Direct IO support for compaction reads Из свежих performance-изменений в Cassandra trunk: https://issues.apache.org/jira/browse/CASSANDRA-19987 В процессе выполнения операции compaction Cassandra читает набор SSTable-файлов, выполняет слияние данных и записывает результат в новые SSTables. При чтении файлов с диска по умолчанию данные попадают в файловый кэш операционной системы (Linux page cache) и могут вытеснять уже закэшированные данные. Аналогичная ситуация происходит и при обработке пользовательских запросов: данные читаются с диска и также загружаются в page cache. В результате, во время выполнения compaction возможна ситуация, когда «горячие» данные, необходимые для запросов, вытесняются из page cache (aka page cache pollution). В рамках CASSANDRA-19987 в Cassandra trunk был добавлен режим, при котором compaction читает SSTable-файлы с использованием Direct IO. В этом режиме данные читаются напрямую с диска, минуя загрузку в page cache. Это позволяет снизить негативное влияние compaction на время отклика для операций чтения. Для управления этим поведением добавлена новая настройка в cassandra.yaml:
# Set the disk access mode for reading SSTables during compaction. The allowed values are:
# - auto: inherit from disk_access_mode (default)
# - direct: use direct I/O for compaction reads, bypassing the OS page cache
# compaction_read_disk_access_mode: auto
Примечания: 1) Для cursor compaction эта возможность пока еще не поддержана: https://issues.apache.org/jira/browse/CASSANDRA-21147 2) Есть аналогичная идея для процесса записи: https://issues.apache.org/jira/browse/CASSANDRA-21134

JDK21 support merged to Cassandra trunk! https://issues.apache.org/jira/browse/CASSANDRA-18831 Теперь у нас есть доступ к GenZGC, новому Java API и улучшениям производительности, доступным в этом LTS-релизе JDK. Я добавил в тикет черновые результаты бенчмарков: примерно +8% к пропускной способности для G1. GenZGC показывает сопоставимый уровень пропускной способности, но со значительно меньшими паузами. Следующая остановка: JDK 25 — compressed object headers и generational Shenandoah 🚀 P.S. Даже с современными GC лучшая стратегия оптимизации всё та же: сокращать количество выделяемых объектов в горячем коде (очередной патч на эту тему у меня на подходе)

Оптимизация memtable flushing, часть 2 Сами улучшения, в основном, заключаются в упрощении логики для типичного сценария: общий код, используемый для разных целей, можно кастомизировать под конкретные условия и пропустить некоторые ненужные шаги. Конкретные идеи я перечислил в описании тикета. Из нетипичного: в рамках flushing у нас много операций с Cell — значением колонки в конкретной строке. Эти операции выполняются очень часто, миллионы раз в секунду, и на этом уровне даже мелкие накладные расходы становятся заметными. Одним из таких расходов является megamorphic virtual call. В данном конкретном случае техника call site split позволила снизить эти расходы и улучшить inlining в ряде горячих мест. Подробнее об этом: - https://shipilev.net/blog/2015/black-magic-method-dispatch/ - https://shipilev.net/jvm/anatomy-quarks/16-megamorphic-virtual-calls/ Кстати, async-profiler умеет показывать megamorphic virtual calls: https://github.com/async-profiler/async-profiler/blob/master/docs/AdvancedStacktraceFeatures.md

Оптимизация memtable flushing, часть 1 https://issues.apache.org/jira/browse/CASSANDRA-21083 Залил очередное perf-улучшение в
Оптимизация memtable flushing, часть 1 https://issues.apache.org/jira/browse/CASSANDRA-21083 Залил очередное perf-улучшение в Cassandra trunk — на этот раз в логике memtable flushing. Хотя эта логика напрямую не связана с обработкой запросов, она тем не менее заметно влияет на производительность: 1) Запись в memtable возможна только при наличии свободной памяти, которая освобождается за счёт периодической flushing-активности. Если мы не успеваем сбрасывать данные из памяти на диск, то либо падаем с OOM, либо вынуждены притормаживать потоки записи. Таким образом, опосредованно мы не можем писать в среднем быстрее (с точки зрения пропускной способности), чем успеваем сбрасывать данные на диск. 2) Потоки, выполняющие flushing, активно потребляют ресурсы (в частности CPU) и тем самым конкурируют за общие ресурсы с потоками записи. В рамках улучшения я также добавил ряд дополнительных статистик для операции flushing, в частности CPU time и объём памяти, выделенной в рамках этой операции в Java heap.

Low-allocation compaction is in trunk Недавно упомянутая выше реализация логики compaction была замержена в trunk Apache Cassandra. В моём синтетическом тесте ускорение по времени составило примерно 2×. Мы уже обсудили результаты с Nitsan — там всё ещё есть пространство для дальнейших оптимизаций. При этом объём аллокаций в Java heap снизился практически до нуля. На текущий момент новая реализация не является полной заменой существующего механизма compaction: реализована не вся функциональность, и в ряде случаев Cassandra по-прежнему будет использовать старую логику. В частности, low-allocation compaction пока не поддерживается в следующих сценариях: - complex columns (примечание: frozen-колонки Cassandra трактует как simple колонки) - таблицы с secondary indexes - BTI формат SSTable не поддерживается (только BIG) - counter таблицы - partitioner, отличный от Murmur3Partitioner и LocalPartitioner - nodetool garbagecollect - validation compaction Эти ограничения не являются принципиальными — в дальнейшем их можно будет постепенно снять по мере развития реализации.

Cassandra user survey 2025 https://docs.google.com/forms/d/e/1FAIpQLSdRGaQ1YMSA6ahF60FrnY5oilFUqSTT-gf5Um8FvrXl4uQgcA/viewform если вы работаете или планируете работать с Cassandra, еще есть возможность поучаствовать в этом опросе, это очень поможет сообществу с вектором развития

UTF-8 validation Немного подтюнил валидацию UTF-8 строк в Cassandra (тип text для колонок). Когда клиент отправляет запросы в Cassandra, ей нужно убедиться, что передаваемые данные имеют корректный формат и соответствуют типу конкретной колонки. Часто используемая оптимизация (её можно найти в Guava и OpenJDK, к примеру) — начинать с упрощённой проверки на ASCII-символы и переходить к более сложной логике только в том случае, если встречаются байты за пределами ASCII (то есть с установленным старшим битом). В реальной жизни это происходит довольно часто: по спецификации поле может быть UTF-8, но на практике почти всегда содержит только ASCII. Эту идею я и применил. В сочетании с дополнительными оптимизациями это дало неплохой прирост производительности для коротких ASCII-строк:
     [java] UTF8ValidatorBench.testOldBimorphic                        avgt   15  30.383 ± 0.696  ns/op
     [java] UTF8ValidatorBench.testNewBimorphic                        avgt   15  11.405 ± 0.172  ns/op

     [java] UTF8ValidatorBench.testOldMonomorphicArray                 avgt   15  18.528 ± 0.785  ns/op
     [java] UTF8ValidatorBench.testNewMonomorphicArray                 avgt   15   8.791 ± 0.070  ns/op

     [java] UTF8ValidatorBench.testOldMonomorphicHeapByteBuffer        avgt   15  27.887 ± 0.161  ns/op
     [java] UTF8ValidatorBench.testNewMonomorphicHeapByteBuffer        avgt   15  11.705 ± 0.213  ns/op
Больше бенчмарков и код можно найти здесь: https://issues.apache.org/jira/browse/CASSANDRA-21075 Дополнительная интересная ссылка по теме: https://lemire.me/blog/2018/10/16/validating-utf-8-bytes-java-edition/ P.S. Говорят, с Vector API можно сделать ещё быстрее, но, пожалуй, сначала дождёмся его стабильной версии 🙂

https://inside.java/ - интересный источник о том, что новенького происходит во внутренностях OpenJDK в частности, какие улучшения в производительности были сделаны в очередных релизах JDK К примеру: https://inside.java/2025/10/20/jdk-25-performance-improvements/ https://inside.java/2025/03/19/performance-improvements-in-jdk24/

58. Apache Cassandra, часть 3: читаем данные. Как работает чтение из Кассандры? В гостях Дима Константинов. Первая часть: htt
58. Apache Cassandra, часть 3: читаем данные. Как работает чтение из Кассандры? В гостях Дима Константинов.    Первая часть: https://t.me/tfeat/145  Вторая часть: https://t.me/tfeat/151  --   Доклад про процесс чтения из Cassandra: https://www.youtube.com/watch?v=zYF0wXpOybQ&list=PLK4DgKoWPVSLEwmNu0oQt4SsnYgrs2Qey&index=3  https://sre.google/sre-book/addressing-cascading-failures/    Про выбор реплики: https://cassandra.apache.org/doc/latest/cassandra/managing/operating/snitch.html#dynamic-snitching  https://www.elastic.co/blog/improving-response-latency-in-elasticsearch-with-adaptive-replica-selection    Пагинация: https://docs.datastax.com/en/developer/java-driver/4.17/manual/core/paging/index.html    Фильтры Блума: https://cassandra.apache.org/doc/5.0/cassandra/managing/operating/bloom_filters.html    Сжатие: https://cassandra.apache.org/doc/5.0/cassandra/managing/operating/compression.html  https://issues.apache.org/jira/browse/CASSANDRA-20902  -- Для тех, кто думает о смене работы: рекомендую канал Peers Job Board . Ребята вручную отбирают IT-вакансии от стартапов и корпораций, в проверенных компаниях. @peersjobboard -- 🎧 Слушать в Apple Podcasts | Spotify

Третья, заключительная, часть часть подкаста у Саши Пахомова. Читать,

57. Apache Cassandra, часть 2: как работает запись. Вторая часть про Кассандру. Разбираемся в том, как работает запись данных
57. Apache Cassandra, часть 2: как работает запись. Вторая часть про Кассандру. Разбираемся в том, как работает запись данных. В гостях Дима Константинов. Первая часть: https://t.me/tfeat/145 -- Альтер эго Саши @sashimi_pub --- 🎧 Слушать в Apple Podcasts | Spotify | YouTube | браузер

Вышла вторая часть подкаста у Саши Пахомова - Две башни Запись в Cassandra

Reduce contention in MemtableAllocator.allocate on write, часть 2 Все эти улучшения дали заметный прирост пропускной способно
Reduce contention in MemtableAllocator.allocate on write, часть 2 Все эти улучшения дали заметный прирост пропускной способности при вставке данных. Синтетический тест 1 Cassandra node: m8i.4xlarge (16 vCPU, x86_64, 64 GiB RAM, EBS) Схема: 1 partition key (text), 1 clustering (text), 5 value columns (text) Нагрузка: batch вставка по 10 строк До : 0'872k строк/сек После: 1'590k строк/сек Альтернативой могло бы быть выделение и учёт памяти отдельно для каждого потока (аналог Java TLAB). Однако этот механизм должен работать для каждой таблицы в отдельности. В итоге число TLAB стало бы равно число потоков × число таблиц, что приводило бы к значительным накладным расходам и/или усложняло бы логику управления памятью.

Cassandra & Beyond - Статистика и аналитика Telegram-канала @cassandra_beyond