apache cassandra что это

Мой опыт внедрения Apache Cassandra

Как и большинство NoSQL-решений, C* подвержена одной крайне неприятной эпидемии: она является отличным инструментом для узкого класса задач, но позиционируется евангелистами как очередная серебряная пуля по хранению данных. В этой статье я расскажу о своём опыте внедрения C* в (сравнительно) нагруженный проект веб-аналитики. Она будет полезна всем, кто стоит перед выбором масштабируемого хранилища данных, и развенчает мифы и заблуждения об этом инструменте.

apache cassandra что это

Для начала о позитивных моментах. Как я и сказал раньше, с основными своими задачами C* справляется на Ура. Она была создана для быстрой записи, масштабируемости и отказоустойчивости, и в этом она, наверное, лучшая: я ещё не встречал более простого управления кластером, и за всё это время она меня не подвела ни разу. Однако, самая большая проблема C* в том, что её область применения гораздо уже, чем может показаться из документации. И далее я по пунктам расскажу почему.

CQL — это не SQL

Честно говоря, я вообще не понимаю, зачем разработчики C* решили создать CQL. Он запутывает и дезориентирует, создаёт ложные впечатления о специфике работы C*. Вот вам несколько фактов:

Судя по всему, CQL был создан, чтобы популяризовать эту БД среди новичков, пытаясь скрыть самые важные фундаментальные понятия в работе этой БД.

Особенности проектирования данных

Главный принцип при проектировании данных в C* — «SELECT-driven model». Вы проектируете данные так, чтобы вы их смогли потом получить с помощью SELECT. В рамках key-value wide-row хранилища это подразумевает очень сильную денормализацию. Вы не просто денормализуете данные, как вы раньше привыкли это делать в реляционных БД, вы фактически создаёте отдельную таблицу под каждый запрос. И во многих проектах (там, где очень много данных по объёму) это даёт либо огромный overhead во время map/reduce и агрегации, либо огромный overhead по объёму хранимых данных.

И да, вам сразу стоит быть готовым к тому, что без распределённого агрегирования (Hadoop, Spark, Hive и т.д.) эта БД бесполезна. Разработчики обещают в следующей версии операторы для агрегации данных в CQL, но можете особо не надеяться на них. По архитектуре этой БД ясно, что они будут работать только внутри одной строки.

Каунтеры

Отвожу этому типу данных в этой БД свой собственный раздел, и вот почему: изначально, когда я начал внедрять C* в свой проект, я очень обрадовался: для веб-аналитики очень круто иметь атомарные каунтеры, они очень сильно упрощают систему. Но потом я понял простую истину: никогда, слышите? НИКОГДА не используйте каунтеры в C* (по крайней мере в версии до 2.1.* включительно). Дело в том, что этот тип данных противоречит всей идеологии этой БД, и из-за этого у него огромное количество проблем. Если вы спросите у любого специалиста по C* про каунтеры, он в ответ начнёт лишь злобно хихикать.

Суть расхождения идеологии каунтеров и самой БД в том, что все операции в C* — идемпотентны (т.е. повторное применении операции не изменяет результата). Именно это даёт безотказную архитектуру при падении узлов, датацентров, проблемах со связью и т.п. Каунтеры же нарушают этот принцип, и внутри сделаны через «light transactions» — сначала считать значение, потом увеличить его. И это вызывает много проблем. В общем, если вам нужны счётчики, лучше воспользуйтесь Redis-прослойкой, а в С* уже складывайте окончательное значение.

На этом пока всё. Выбирайте инструменты с умом. Если что-то кажется слишком хорошим, чтобы быть правдой, то возможно, так оно и есть.

Источник

Apache Cassandra

Avinash Lakshman, Prashant Malik

Apache Cassandra — распределённая система управления базами данных, относящаяся к классу noSQL-систем и рассчитанная на создание высокомасштабируемых и надёжных хранилищ огромных массивов данных, представленных в виде хэша.

Содержание

Обзор

СУБД Cassandra написана на языке Java и включает в себя полностью распределённую hash-систему Dynamo, что обеспечивает практически линейную масштабируемость при увеличении объёма данных. Cassandra использует модель хранения данных на базе семейства столбцов (ColumnFamily), что отличается от систем, подобных memcachedb, которые хранят данные только в связке ключ/значение, возможностью организовать хранение хэшей с несколькими уровнями вложенности. Cassandra относится к категории хранилищ, повышенно устойчивых к сбоям: помещённые в БД данные автоматически реплицируются на несколько узлов распредёленной сети или даже равномерно распределяются в нескольких дата-центрах. При сбое узла, его функции на лету подхватываются другими узлами. Добавление новых узлов в кластер и обновление версии Cassandra производится на лету, без дополнительного ручного вмешательства и переконфигурации других узлов. Тем не менее настоятельно рекомендуется заново сгенерировать токены для каждого узла, включая существующие, чтобы не испортить распределение нагрузки. Генерации ключей для существующих узлов можно избежать в случае кратного увеличение количества узлов(в 2 раза в 3 раза и т. д.).

Источник

Apache Cassandra + Apache Ignite — как совместить лучшее

Apache Cassandra — это одна из популярных распределенных дисковых NoSQL баз данных с открытым исходным кодом. Она применяется в ключевых частях инфраструктуры такими гигантами как Netflix, eBay, Expedia, и снискала популярность за свою скорость, способность линейно масштабироваться на тысячи узлов и “best-in-class” репликацию между различными центрами обработки данных.

Apache Ignite — это In-Memory Computing Platform, платформа для распределенного хранения данных в оперативной памяти и распределенных вычислений по ним в реальном времени с поддержкой JCache, SQL99, ACID-транзакциями и базовой алгеброй машинного обучения.

Apache Cassandra является классическим решением в своей области. Как и в случае с любым специализированным решением, её преимущества достигнуты благодаря ряду компромиссов, значительная часть которых вызвана ограничениями дисковых хранилищ данных. Cassandra оптимизирована под максимально быструю работу с ними в ущерб остальному. Примеры компромиссов: отсутствие ACID-транзакций и поддержки SQL, невозможность произвольных транзакционных и аналитических транзакций, если под них заранее не адаптированы данные. Эти компромиссы, в свою очередь, вызывают закономерные затруднения у пользователей, приводя к некорректному использованию продукта и негативному опыту, либо вынуждая разделять данные между различными видами хранилищ, фрагментируя инфраструктуру и усложняя логику сохранения данных в приложениях.

Возможное решение проблемы — использование Cassandra в связке с Apache Ignite. Это позволит сохранить ключевые преимущества Cassandra, при этом скомпенсировав ее недостатки за счет симбиоза двух систем.

Как? Читайте дальше, и смотрите пример кода.

apache cassandra что это

Ограничения Cassandra

Для начала хочу кратко пройтись по основным ограничениям Cassandra, с которыми будем работать:

Как же можно обойти эти ограничения?

Я бы сказал, что классическим вариантом является фрагментация данных, когда часть лежит в Cassandra, а часть — в других системах, которые поддерживают необходимые гарантии.

Минусы этого подхода, которые видны навскидку: увеличение сложности (а значит, потенциально, и ухудшение скорости и качества) разработки и поддержки приложений. Намного проще стучаться в одни ворота, нежели на уровне приложения или слоя микросервисов совмещать разрозненную информацию из различных источников. Также деградация любой из двух систем может приводить к значительным негативным последствиям, вынуждая инфраструктрную команду гнаться сразу за двумя зайцами.

Apache Ignite

Ещё один способ — поставить другую систему поверх Cassandra, разделив ответственность между ними. Я считаю, что Apache Ignite — идеальный кандидат для этой схемы:

Кластер Apache Ignite вбирает в себя из Apache Cassandra все или часть данных (например, за исключением архивных), по которым нужно выполнять запросы, после чего работает в режиме write-through, самостоятельно обслуживая API- или SQL-запросы на чтение, и дублируя в синхронном или асинхронном режиме запросы на запись в Cassandra, надежно сохраняя их на диск.

Далее эти данные анализируются в реальном времени, могут использоваться средства визуализации наподобие Tableau, применяться распределенные алгоритмы машинного обучения, а также формироваться витрины.

А на примере?

Далее я приведу пример простой «синтетической» интеграции Apache Cassandra и Apache Ignite, чтобы показать, как это работает и что это совсем не сложно, пусть и требует определенной доли boilerplate-кода.

Для начала я создам необходимые таблицы в Cassandra и заполню их данными, затем инициализирую Java-проект и напишу DTO-классы, после чего покажу основную часть — конфигурирование Apache Ignite для работы с Cassandra.

Я буду использовать Mac OS Sierra, Cassandra 3.10 и Apache Ignite 2.0. В Linux команды должны быть аналогичны.

Cassandra: таблицы и данные

/Downloads, пройдя по ссылке, либо используя curl/wget.

Далее зайдем в директорию и распакуем его:

Запустим Cassandra с настройками по умолчанию, для тестирования этого будет достаточно.

Далее запустим интерактивный шелл Cassandra и создадим тестовые структуры данных (выберем обычный суррогатный id как ключ — для таблиц в Cassandra зачастую имеет смысл выбирать ключи, более осмысленные с точки зрения последующего извлечения данных, но мы упростим пример):

Проверим, что все данные записались корректно:

cqlsh:ignitetest> SELECT * FROM catalog_category;

id | description | name | parentId
—-+———————————————+———————+————
1 | Различная бытовая техника для вашего дома! | Бытовая техника | null
2 | Самые холодные холодильники! | Холодильники | 1
3 | Замечательные стиралки! | Стиральные машинки | 1

(3 rows)
cqlsh:ignitetest> SELECT * FROM catalog_good;

id | categoryId | description | name | oldPrice | price
—-+————-+—————————+———————-+————+———
1 | 2 | Лучший холодильник 2027! | Холодильник Buzzword | null | 1000
2 | 2 | Дешевле не найти! | Холодильник Foobar | 900 | 300
4 | 3 | Стирает, отжимает, сушит! | Машинка Habr# | null | 10000
3 | 2 | Люкс на вашей кухне! | Холодильник Barbaz | 300000 | 500000

Инициализация Java-проекта

Есть 2 способа работы с Ignite: можно скачать дистрибутив с сайта ignite.apache.org, подложить ему необходимые Jar-файлы с собственными классами и XML с конфигурацией, либо использовать Ignite как зависимость в Java-проекте. В этой статье я рассмотрю второй вариант.

Создадим новый проект — я буду использовать maven как классический и понятный максимально широкой, на мой взгляд, аудитории инструмент.

В зависимости пропишем:

Далее необходимо создать DTO-классы, которые будут представлять таблицы Cassandra в мире Java:

Мы помечаем аннотацией @QuerySqlField те поля, которые будут участвовать в SQL-запросах. Если поле не помечено данной аннотацией, его невозможно будет извлечь его посредством SQL или фильтровать по нему.

Также можно сделать более тонкие настройки для определения индексов и полнотекстовых индексов, которые выходят за рамки данного примера. Подробнее о настройке SQL в Apache Ignite можно прочитать в соответствующем разделе документации.

Конфигурация Apache Ignite

Создадим в src/main/resources нашу конфигурацию в файле apacheignite-cassandra.xml (название выбрано произвольно). Я приведу полную конфигурацию, которая достаточно объемна, после чего рассмотрю ее по частям:

Формат конфигурации — Spring Beans.

Конфигурацию можно поделить на два раздела: определение DataSource для установки связи с Cassandra и определение настроек Apache Ignite, которые сводятся в данном примере к указанию рабочих кешей, полностью соответствующих таблицам в Cassandra.

Первая часть конфигурации лаконична:

Мы определяем источник данных Cassandra, указываем адреса, по которым можно попытаться установить соединение.

Первый кеш — представляющий таблицу catalog_category:

В нем включаем режим сквозных чтения и записи (если будем что-то писать в кеш, операция записи будет автоматически дублироваться в Cassandra), указываем, что в SQL будет использоваться схема catalog_category, а также перечисляем типы, которые будут храниться в этом кеше и должны быть обработаны для обращения к ним через SQL. Типы указываются всегда парами ключ-значение, поэтому количество элементов списка всегда должно быть четным.

Конфигурация меппинга выглядит достаточно интутивно понятно:

Подробнее о более тонких настройках меппинга, которые выходят за рамки данного примера, можно прочитать в соответствующем разделе документации.

Конфигурация второго кеша, содержащего данные о товарах аналогична.

Запуск

Для запуска создадим класс com.gridgain.test.Starter :

Здесь мы используем инструкцию Ignition.start(. ) для запуска узла Apache Ignite, указав в качестве источника конфигурации лежащий на classpath файл apacheignite-cassandra.xml.

Для выполнения SQL-запросов можно использовать любой клиент, который поддерживает JDBC, например, встроенный в IntelliJ IDEA, либо SquirrelSQL. В последнем случае, например, нужно будет добавить драйвер Apache Ignite (который находится в Jar-файле ignite-core, его можно скачать в составе дистрибутива):

apache cassandra что это

Создадим новое соединение по URL вида jdbc:ignite://localhost/CatalogGood, где localhost — адрес одного из узлов Apache Ignite, а CatalogGood — кеш, к которому будут идти по умолчанию запросы.

apache cassandra что это

Пара примеров возможных SQL-запросов:

goodNamegoodPricecategoryparentCategory
Холодильник Buzzword1000ХолодильникиБытовая техника
Холодильник Foobar300ХолодильникиБытовая техника
Холодильник Barbaz500000ХолодильникиБытовая техника
Машинка Habr#10000Стиральные машинкиБытовая техника
nameavgPrice
Холодильники650
Стиральные машинки10000

Заключение

На этом простом примере можно видеть, как используя Apache Ignite можно поверх Apache Cassandra поднять распределенный SQL-движок с ACID-транзакциями и скоростью оперативной памяти.

Столкнувшись с Apache Cassandra в существующей инфраструктуре либо в greenfield-проекте, вспомните об этой статье и о том, что Cassandra хороша со вкусом Ignite. Или можно уже сейчас попробовать сочинить какой-то проект, например, из мира интернета вещей, использующий сильные стороны Ignite и Cassandra.

Источник

Apache Cassandra. СУБД с распределенной системой хранения данных

Физические понятия

Под физическими понятиями я буду подразумевать прежде всего структурные элементы архитектуры, которые однозначно можно выделить в самостоятельные единицы на том или ином уровне. В этом разделе я не планирую затрагивать понятия, которые относятся к механизмам оперирования данными.

Узел 1 (Node)

Базовый компонент всей архитектуры. Именно на узлах хранятся данные. Теоретически в инфраструктуре может существовать лишь один 2 узел, но тогда ни о какой отказоустойчивости и распределенности хранения говорить не приходится. На практике рекомендуется, чтобы было такое количество узлов, которое удовлетворяет потребностям в производительности с небольшим запасом (в 20-30%), на случай выхода из строя одного или нескольких узлов, а также для удовлетворения будущих потребностей в расширении.

В элементарном виде узел можно представить следующим образом:

apache cassandra что это

В реальной обстановке узел — это физический или виртуальный сервер с операционной системой (например, Debian) и установленной на неё СУБД Cassandra, имеющий доступ к сети для взаимодействия с клиентами.

Стойка (Rack)

Виртуальный объект, в буквальном смысле представляющий из себя стойку серверов внутри центра обработки данных. Введен для минимизации рисков физических сбоев (проблемы с питанием, охлаждением или проблемы с сетью) внутри одной стойки.

apache cassandra что это

Хоть и понятие стойки чисто виртуальное, на практике рекомендуется придерживаться существующего физического расположения узлов и по возможности разносить их по разным стойкам.

Центр обработки данных 3 (Data Center)

Ни что иное, как логическое объединение стоек. Кластер (см. ниже) может существовать как в рамках одного, так и нескольких центров обработки данных. Это значительно влияет на репликацию данных.

Обобщенное представление кластера:

apache cassandra что это

Учитывая минимально двойное резервирование, необходимо иметь два центра обработки данных, в каждом из которых будет по две стойки, по одному узлу в стойке. Таким образом мы получаем минимальное количество узлов, необходимое для реализации приемлемого уровня отказоустойчивости — 4 штуки.

Кластер 4 (Cluster)

Набор узлов, который образует полное и замкнутое кольцо маркеров (читай ниже).

apache cassandra что это

Логические понятия

Рассмотрев выше физические элементы архитектуры СУБД Cassandra, пришло время заглянуть на более низкий уровень взаимодействия и попытаться описать основные понятия при оперировании данными. Надо сразу оговориться, что речь о логической структуре данных внутри БД идти не будет, поскольку это относится несколько к другой области — модели данных.

Раздел 5 (Partition)

Представляет из себя структурную единицу данных, состоящую из одной или более записи (row). Разные разделы хранятся на разных узлах (или разных наборах узлов). Cassandra самостоятельно определяет узел, на котором будет храниться тот или иной раздел с помощью определенного механизма, дословно называемого распределитель (partitioner). По сути распределитель — хэш-функция 6 , входным параметром для которой является ключ записи (row key); на выходе получаем значение этой хэш-функции, называемое маркером 7 (token). Поскольку хэш-функция гарантирует получение из входных данных произвольного размера результат в виде данных фиксированного размера (это её основная особенность), то можно не беспокоиться о размере или типе входного параметра. Кроме того, если вы будете друг за другом вычислять хэш-функцию для одного и того же входного параметра, то на выходе всегда будете получать один и тот же маркер, что гарантирует всегда точное определение узла с нужными данными как в процессе чтения, так и в процессе записи (например, при обновлении данных). Распределитель по умолчанию — Murmur3Partitioner 8 , однако в предыдущих версиях (до 1.2) использовался RandomPartitioner 9 и другие (см. соответств. разделы 10 11 документации).

В официальной документации 12 достаточно подробно расписан принцип работы разделения данных:

Data Distribution in the Ring

In Cassandra, the total amount of data managed by the cluster is represented as a ring. The ring is divided into ranges equal to the number of nodes, with each node being responsible for one or more ranges of the data. Before a node can join the ring, it must be assigned a token. The token value determines the node’s position in the ring and its range of data. Column family data is partitioned across the nodes based on the row key. To determine the node where the first replica of a row will live, the ring is walked clockwise until it locates the node with a token value greater than that of the row key. Each node is responsible for the region of the ring between itself (inclusive) and its predecessor (exclusive). With the nodes sorted in token order, the last node is considered the predecessor of the first node; hence the ring representation.

Для лучшего понимания, перевод:

«В Cassandra итоговый объем данных, обслуживаемых кластером, представляется в виде кольца. Кольцо разделено на диапазоны, количество которых равно количеству узлов, каждый узел отвечает за один или более диапазона данных. Перед присоединением узла к кластеру, ему должен быть назначен маркер. Значение маркера определяет позицию узла в кольце и диапазон данных, за который он будет отвечать. Данные колоночного семейства разделены по узлам, основываясь на ключе записи. Чтобы определить узел, где будет «жить» первый экземпляр записи, необходимо пройти по кольцу по часовой стрелке пока не встретится узел с маркером, который больше, чем маркер ключа записи. Каждый узел ответственен за участок кольца между самим собой (включая свой маркер) и своим предшественником (исключая его маркер). Узлы отсортированы в порядке возрастания маркеров, последнему узлу предшествует первый и таким образом образуется представление в виде кольца».

Пример, идеально иллюстрирующий весь этот механизм, есть в официальных видеороликах 13 и я позволю себе его позаимствовать:

apache cassandra что это

В каждом центре обработки данных одинаковым цветом обозначены узлы, которые хранят одинаковые реплики. На кольце ниже также соответствующим цветом обозначены диапазоны маркеров, за которые отвечают определенные узлы.

Реплика (Replica)

Чтобы не потерять данные при выходе из строя одного или более узла, необходимо обеспечить некоторую избыточность, то есть хранить копии (реплики) одних и тех же разделов на разных узлах одновременно. Количество хранимых копий данных определяется коэффициентом копирования или, другими словами, фактором репликации 14 (replication factor). Разумеется копии данных хранятся на разных узлах. Все копии одних и тех же данных абсолютно равнозначны, не существует первичных или вторичных реплик.

Процесс распределения копий называется репликацией данных (data replication).

Механизм распространения реплик называется стратегией репликации (replication strategy), существует две стратегии:

Важным механизмом распространения реплик является уровень согласованности 15 (consistency level), который отвечает за обеспечение степени согласованности данных в репликах. Уровень согласованности определяется для чтения и записи данных:

Процесс взаимодействия

Для обмена информацией о расположении и состоянии друг друга узлы кластера используют одноранговый 16 протокол под названием Gossip 17 18 . Ежесекундно каждый узел отправляет максимум трем другим узлам информацию о самом себе, а также информацию о других узлах (полученную по тому же Gossip), которая ему известна. Согласованность информации поддерживается с помощью версий сообщений, старые данные затираются. Очень важно, чтобы узлы были осведомлены о состоянии друг друга, ведь если какие-либо из них выйдут из строя, необходимо предотвратить маршрутизацию к ним клиентских запросов. Конечно о выходе узла в кластере станет известно не сразу из-за некоторых задержек в обмене информации, однако этот нюанс взаимодействия также можно регулировать, таким образом определяя чувствительность 19 к сбоям.

Процесс инициализации 20 21 всего кластера начинается с запуска так называемых узлов-источников (seed node), которые содержат в себе информацию о других узлах, данные о топологии кольца. Необходимо иметь как минимум один узел-источник на центр обработки данных, но рекомендуется не меньше двух, все также в угоду отказоустойчивости. Далее должны быть запущены обычные узлы, которые обратятся за необходимой информацией к узлам-источникам. После этого процесс взаимодействия осуществляется обычным образом.

Источник

Apache Cassandra 4.0: бенчмарки

apache cassandra что это

Apache Cassandra 4.0 приближается к бете (прим. переводчика: на текущий момент уже доступна бета 4, выпущенная в конце декабря 2020), и это первая версия, которая будет поддерживать JDK 11 и более поздних версий. Пользователей Apache Cassandra, очевидно, волнует задержка, так что мы возлагаем большие надежды на ZGC — новый сборщик мусора с низкой задержкой, представленный в JDK 11.

В JDK 14 он был выпущен уже в GA-версии, и нам было очень интересно оценить, насколько он подходит для кластеров Apache Cassandra. Мы хотели сравнить производительность Apache Cassandra 3.11.6 и 4.0 и проверить, подходит ли Shenandoah, сборщик мусора от Red Hat, для продакшена. Спойлер: Cassandra 4.0 значительно лучше по производительности сама по себе, а с новыми сборщиками мусора (ZGC и особенно Shenandoah) будет совсем хорошо.

Методология бенчмарков

Мы провели следующие бенчмарки, используя утилиту tlp-cluster для развертывания и настройки кластеров Apache Cassandra в AWS и tlp-stress — для создания нагрузок и сбора метрик. Все эти инструменты доступны в опенсорсе, все бенчмарки легко воспроизвести при наличии учетки AWS.

Кластеры состояли из трех нод на инстансах r3.2xlarge и одной стресс-ноды на c3.2xlarge.

Мы использовали дефолтные параметры Apache Cassandra, кроме настроек кучи и сборщика мусора.

Для развертывания и настройки кластера мы взяли последний релиз tlp-cluster. Недавно мы добавили скрипты, чтобы автоматизировать создание кластера и установку Reaper и Medusa.

Установите и настройте tlp-cluster по инструкциям в документации, чтобы создать такие же кластеры, которые мы использовали для бенчмарков:

Примечание. Чтобы воспроизвести схожие условия, мы использовали для всех тестов один набор инстансов EC2.

Мы сделали апгрейд с Cassandra 3.11.6 на Cassandra 4.0

alpha4 и меняли JDK следующим кодом:

Мы использовали следующие значения JDK при вызове jabba:

OpenJDK 8 был установлен с помощью Ubuntu apt.

jdk8

jdk8 с Shenandoah

jdk11

jdk11 с Shenandoah

jdk14

CMS (Concurrent Mark Sweep) — это текущий дефолтный сборщик мусора в Apache Cassandra. Он был удален из JDK 14, так что все тесты проводились с JDK 8 или 11.

Для CMS параметры были такие:

Для CMS мы задали максимальный размер кучи 16 ГБ, иначе между сборками будут слишком длинные паузы.

G1GC (сборщик мусора по принципу Garbage-First) настроить легче, чем CMS, потому что он динамически изменяет размер младшего поколения, но лучше работает с большими кучами (от 24 ГБ). Это объясняет, почему он не стал дефолтным сборщиком мусора. Задержки у него выше, чем у настроенного CMS, зато пропускная способность лучше.

Для G1 параметры были такие:

Для версии 4.0 мы использовали JDK 14 в тестах с G1.

ZGC (Z Garbage Collector) — это новейший сборщик мусора в JDK, который минимизирует задержку благодаря паузам stop-the-world меньше 10 мс. Предполагается, что благодаря этому размер кучи не будет влиять на продолжительность пауз, что позволит увеличить его до 16 ТБ. Если так и будет, хранилище вне кучи не понадобится, и некоторые аспекты разработки в Apache Cassandra станут проще.

Для ZGC параметры были такие:

-XX:+UseTransparentHugePages здесь нужен как обходной путь, чтобы избежать включения больших страниц в Linux. В официальной документации по ZGC сказано, что потенциально могут возникать пики задержки, но на практике мы такого не увидели. Может быть, следует протестировать пропускную способность на больших страницах и посмотреть, как это скажется на результате.

ZGC не может использовать compressed oops и не соблюдает порог 32 ГБ. Мы взяли кучу размером 31 ГБ, как и для G1, чтобы у системы был тот же объем свободной оперативки.

Shenandoah

Shenandoah — это сборщик мусора с низкой задержкой от Red Hat. Он доступен как бэкпорт в JDK 8 и 11 и в mainline-сборках OpenJDK начиная с Java 13.

Как и ZGC, Shenandoah стремится к параллелизму, чтобы паузы не зависели от размера кучи.
Для Shenandoah параметры были такие:

Shenandoah может использовать compressed oops, а значит лучше работает с кучами размером чуть меньше 32 ГБ.

Конфигурация Cassandra 4.0 JVM

Cassandra 4.0 поставляется с отдельными файлами jvm.options для Java 8 и Java 11, а именно:

Рабочие нагрузки

В бенчмарках мы использовали восемь потоков с ограничением скорости и соотношением записи и чтения 80/20%. tlp-stress широко использует асинхронные запросы, которые легко могут перегрузить ноды Cassandra с ограниченным числом стресс-потоков. В нагрузочных тестах каждый поток отправлял 50 параллельных запросов за раз. Мы создали keyspace с коэффициентом репликации 3, и все запросы выполнялись на уровне согласованности LOCAL_ONE.

Все сборщики мусора и версии Cassandra тестировались по нарастанию — 25к, 40к, 45к и 50к операций в секунду, — чтобы оценить производительность при разных уровнях нагрузки.

Все рабочие нагрузки выполнялись 30 минут, загружая от 5 до 16 ГБ данных на ноду и допуская нагрузку от compaction в разумной степени.

Примечание. Мы не пытались оценить максимальную производительность Cassandra, которую можно по-разному настроить в зависимости от рабочей нагрузки. И настраивать сборщики мусора мы тоже не планировали, потому что у них множество параметров для разных нагрузок. Мы просто хотели честно сравнить разные сборщики мусора, в основном на дефолтных параметрах, при одинаковой нагрузке в Cassandra.

Результаты бенчмарков

3.11.6, 25-40к операций/с:

apache cassandra что это

4.0, 25-40к операций/с:

apache cassandra что это

4.0, 45-50к операций/с:

apache cassandra что это

apache cassandra что это

В плане пропускной способности Cassandra 3.11.6 осилила 41к операций в секунду, а Cassandra 4.0 — 51к, то есть на 25% больше. В обоих случаях использовался CMS. В версии 4.0 много улучшений, которые объясняют эти результаты, особенно в вопросах нагрузки на кучу, вызванной compaction (см. CASSANDRA-14654, например).

Shenandoah в jdk8 на Cassandra 3.11.6 не достигает максимальной пропускной способности в тесте на 40к операций в секунду — появляются невыполненные запросы. С jdk11 и Cassandra 4.0 результат получше — 49,6к, почти как у CMS. У G1 и Shenandoah с jdk 8 получилось 36к/с на Cassandra 3.11.6.

G1, видимо, усовершенствован в jdk14 и показал себя немного лучше, чем с jdk11, — 47 против 50к/с.

ZGC не дотянул до конкурентов ни с jdk11, ни с jdk14, показав 41к/с максимум.

apache cassandra что это

apache cassandra что это

apache cassandra что это

apache cassandra что это

apache cassandra что это

apache cassandra что это

При умеренной нагрузке Shenandoah в jdk8 показывает хороший результат на Cassandra 3.11.6, но под высокой нагрузкой серьезно увеличиваются задержки.

С CMS Cassandra 4.0 показывает среднюю задержку для p99 (99-го перцентиля) от 11 до 31 мс при 50к операций в секунду. Средняя задержка операций чтения для p99 при умеренной нагрузке снизилась с 17 мс в Cassandra 3.11.6 до 11,5 мс в Cassandra 4.0, то есть на целых 30%.

В целом Cassandra 4.0 лучше Cassandra 3.11.6 с теми же сборщиками мусора на 25–30% по пропускной способности и задержке.

Shenandoah дает очень низкие задержки при умеренной нагрузке в Cassandra 3.11.6, но с высокими нагрузками справляется не очень.

По задержкам ZGC хорошо себя проявляет при умеренной нагрузке, особенно с jdk14, но при более высокой скорости отстает от Shenandoah. Почти во всех нагрузочных тестах Shenandoah показал минимальные средние задержки для p99 для чтения и записи. Если сложить эти задержки с пропускной способностью в Cassandra 4.0, получится что этот сборщик мусора — неплохой выбор, если вы обновляете версию. Средняя задержка 2,64 мс при чтении для p99 при умеренной нагрузке — это впечатляет. Тем более на клиенте.

G1, в основном, соответствует настроенному максимальному времени паузы 300 мс для максимального значения p99, но с меньшей паузой при высоких нагрузках могут возникать нежелательные эффекты, и пауза может быть больше.

При умеренной нагрузке Shenandoah дает среднюю задержку для p99 на 77% ниже. 2,64 мс — это самый низкий результат. Полезно для сценариев, где важна задержка. По сравнению с CMS в Cassandra 3.11.6 это на целых 85% ниже для операций чтения на p99!

Отдадим должное ZGC в jdk14, который хорошо себя показал при умеренных нагрузках, но с увеличением скорости, увы, не справился. Мы надеемся, что через несколько месяцев он станет лучше и сможет конкурировать с Shenandoah.

Итоги

G1 улучшает юзабилити Cassandra — не нужно настраивать размеры поколений в ущерб производительности. В версии Apache Cassandra 4.0, которая и без того работает гораздо лучше, можно будет использовать сборщики мусора нового поколения, например Shenandoah и ZGC, которые не требуют тщательной настройки и сокращают задержки.

Мы не рекомендуем Shenandoah для Cassandra 3.11.6, поскольку он не справляется с высокими нагрузками, но начиная с jdk11 и Cassandra 4.0 этот сборщик мусора показывает низкие задержки и обеспечивает почти максимальную пропускную способность для базы данных.

Ваши цифры могут отличаться в зависимости от рабочей нагрузки, но результаты позволяют надеяться, что в будущем Apache Cassandra станет неплохим инструментом для сценариев, где особо важны задержки. Во всяком случае, новая версия показала себя гораздо лучше, чем Cassandra 3.11.6.

Загрузите последнюю сборку Apache 4 и попробуйте сами. Будем рады обратной связи тут или в Slack компании ASF.

От редакции: приглашаем на открытую онлайн-конференцию Cassandra Day Russia 2021 в субботу 27 марта. В программе доклады и воркшопы от опытных NoSQL-специалистов.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *