Пример диагностики перегруженных шардов и нехватки ресурса CPU
Как и в предыдущей статье, здесь мы рассматриваем пример диагностики перегруженных шардов и решения этой проблемы. Но в этом случае ситуация осложняется недостатком ресурсов CPU.
Дополнительную информацию о проблемах, диагностируемых в этой статье, см. в следующих материалах:
Статья начинается с описания возникшей проблемы. Затем мы проанализируем графики в Grafana и информацию на вкладке Diagnostics в Embedded UI, чтобы найти решение, и проверим его эффективность.
В конце статьи приводятся шаги по воспроизведению проблемы.
Описание первоначальной проблемы
Вас уведомили о задержках при обработке пользовательских запросов в вашей системе.
Примечание
Речь идёт о запросах к строковой таблице, управляемой data shard'ом.
Рассмотрим графики Latency на панели мониторинга Grafana DB overview и определим, имеет ли отношение наша проблема к кластеру YDB:

См. описание графика
График отображает процентили задержек транзакций на запись данных. Примерно в 10:17:00 эти значения выросли в три-четыре раза.

См. описание графика
График отображает тепловую карту (heatmap) задержек транзакций на запись. Транзакции группируются на основании их задержек, каждая группа (bucket) окрашивается в свой цвет. Таким образом, этот график показывает как количество транзакций, обрабатываемых YDB в секунду (по вертикальной оси), так и распределение задержек среди транзакций (цветовая дифференциация).
К 10:18:00 доля транзакций с задержками от 2 до 4 секунд (Группа 4.0, голубой) выросла примерно в десять раз. Доля транзакций с задержками от 4 до 8 секунд (Группа 8.0, жёлтый) увеличилась в три раза. Доля транзакций с задержками от 8 до 16 секунд (Группа 16.0, красный) уменьшилась в три раза. Доля транзакций с задержками от 16 до 32 секунд (Группа 32.0, синий) практически исчезла. А также выделились новые группы транзакций с ещё более высокими задержками — Группа 64.0 и Группа 128.0.

См. описание графика
График отображает процентили задержек транзакций на чтение данных и демонстрирует рост значений p99.

См. описание графика
График отображает тепловую карту (heatmap) задержек транзакций на чтение данных. Транзакции группируются на основании их задержек, каждая группа (bucket) окрашивается в свой цвет. Таким образом, этот график показывает как количество транзакций, обрабатываемых YDB в секунду (по вертикальной оси), так и распределение задержек среди транзакций (цветовая дифференциация).
К 10:18:00 мы видим рост количества транзакций на чтение начиная с Группы 4.0, но соотношения между группами транзакций остаются примерно одинаковыми.
Таким образом, мы видим, что задержки действительно выросли. Теперь нам необходимо локализовать проблему.
Диагностика
Давайте определим причину роста задержек. Могли ли они увеличиться из-за возросшей нагрузки? Посмотрим на график Requests в секции API details панели мониторинга Grafana DB overview:

Количество пользовательских запросов выросло приблизительно с 8 000 до 13 000 в 10:20:00. Но может ли YDB справиться с увеличившейся нагрузкой без дополнительных аппаратных ресурсов?
Загрузка CPU увеличилась, что видно на графике CPU by execution pool.

Мы видим рост нагрузки на CPU в пуле ресурсов пользователей (красный) и интерконнекта (жёлтый).
Мы также можем взглянуть на общее использование CPU на вкладке Diagnostics в Embedded UI:

Кластер YDB не использует все ресурсы CPU.
Взглянув на секцию DataShard details на панели мониторинга Grafana DB overview, мы увидим, что после роста нагрузки на кластер один из data shard'ов был перегружен (нагрузка на него выросла до 73%).

См. описание графика
Этот график отображает тепловую карту распределения data shard'ов по нагрузке. Каждый data shard потребляет от 0% до 100% ядра CPU. Data shard'ы делятся на десять групп по занимаемой ими доле ядра CPU — 0-10%, 10-20% и т.д. Эта тепловая карта показывает количество data shard'ов в каждой группе.
График показывает два data shard'а, нагрузка на которые изменилась примерно в 10:18:00 — один data shard перешёл в Группу 80, содержащую шарды, нагруженные на 70–80%, а второй — в Группу 60 .
Чтобы определить, какую таблицу обслуживает перегруженный data shard, откроем вкладку Diagnostics > Top shards во встроенном UI:

Мы видим, что один из data shard'ов, обслуживающих таблицу kv_test, нагружен на 73%.
Далее давайте взглянем на информацию о таблице kv_test на вкладке Info:

Важно
Таблица kv_test была создана с включённым партиционированием по нагрузке, но максимальное количество партиций ограничено двумя.
Учитывая, что data shard'ы являются однопоточными компонентами и обрабатывают за раз только один запрос, такой подход неэффективен.
Решение
Нам необходимо увеличить лимит на максимальное количество партиций для таблицы kv_test:
-
Во встроенном UI выберите базу данных.
-
Откройте вкладку Query.
-
Выполните следующий запрос:
ALTER TABLE `kv_test` SET ( AUTO_PARTITIONING_MAX_PARTITIONS_COUNT = 1000 );
Результат
После увеличения максимального лимита на количество партиций для таблицы kv_test перегруженные data shard'ы начали делиться и их количество выросло до шести.

См. описание графика
График показывает, что количество data shard'ов выросло примерно в 10:29:00. Судя по цвету групп, их нагрузка не превышает 50%.
Теперь шесть data shard'ов обрабатывают запросы к таблице kv_test, и ни один из них не перегружен:

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

См. описание графика
Примерно в 10:29:00 процентили задержек упали практически до прежних значений.

См. описание графика
Транзакции на этом графике теперь распределены по трём основным группам:
Группа 8.0— примерно 8% транзакций выполняется с задержкой от 4 до 8 миллисекунд.Группа 16.0— примерно 58% транзакций выполняется с задержкой от 8 до 16 миллисекунд.Группа 32.0— примерно 34% транзакций выполняется с задержкой от 16 до 32 миллисекунд.
Размеры остальных групп незначительны.


Проблема с недостаточным количеством ядер CPU
Однако, если мы откроем диагностику во встроенном UI, то мы увидим предупреждение о том, что кластеру YDB не хватает ресурсов процессора в пользовательском пуле:

Загрузка CPU еще раз увеличилась, что видно на графике CPU by execution pool.

Количество пользовательских запросов выросло приблизительно с 13 000 до 18 000 в 10:30:00.

Решение проблемы с нехваткой ресурсов CPU
Проблему недостатка ресурсов CPU можно решить несколькими способами:
- Увеличить количество ядер для серверов, на которых запущены узлы YDB.
- Увеличить количество ядер, доступных акторной системе узлов кластера YDB, в конфигурации кластера.
- Добавить новые узлы в кластер YDB.
В нашем примере мы увеличим количество ядер CPU на серверах YDB и затем увеличим количество ядер в пуле ресурсов узлов кластера YDB на каждом сервере:
-
Увеличить количество ядер CPU выделенных серверам YDB. В нашем случае мы увеличили количество ядер с 16 до 24.
-
На каждом сервере YDB изменить динамическую конфигурацию кластера:
-
Открыть файл конфигурации
/opt/ydb/cfg/ydbd-config-dynamic.yamlв текстовом редакторе:sudo vim /opt/ydb/cfg/ydbd-config-dynamic.yaml -
Увеличить количество ядер в параметре
cpu_countразделаactor_system_config:actor_system_config: use_auto_config: true node_type: COMPUTE cpu_count: 24
-
-
Чтобы применить новую конфигурацию, перезапустить узлы YDB с помощью утилиты ydbops, ansible или вручную.
Результат
После увеличения количества ядер CPU в кластере YDB предупреждение о недостатке ресурсов CPU пропало:

А теперь давайте проверим производительность.
Количество обрабатываемых запросов увеличилось примерно до 14-15 тысяч в секунду.

Помогло ли добавление ядер CPU снизить задержки?

См. описание графика
На графике опять появилась Группа 4.0 с задержками от 2 до 4 миллисекунд. Группа 8.0 выросла в три раза. Группа 16.0 изменилась незначительно. Практически пропала Группа 32.0.

См. описание графика
Процентили задержек на запись немного снизились, а также прекратились всплески p99.

См. описание графика
График задержек транзакций на чтение стал очень похож на график пишущих транзакций. Вернулась Группа 4.0 с задержками от 2 до 4 миллисекунд, чья доля оказалась еще больше, чем при записи. Группа 4.0 выросла в три раза. Группа 16.0 изменилась незначительно. Практически пропала Группа 32.0.

См. описание графика
Процентили задержек на чтение тоже снизились, а также практически исчезли всплески p99.
Тестовый стенд
Топология
Для этого примера мы использовали кластер YDB из трёх серверов на Ubuntu 22.04 LTS. На каждом сервере был запущен один узел хранения и три узла баз данных, обслуживающих одну и ту же базу данных.
Аппаратная конфигурация
Аппаратные ресурсы серверов (виртуальных машин) приведены ниже:
- Платформа: Intel Broadwell
- Гарантированный уровень производительности vCPU: 100%
- vCPU: 16
- Память: 32 GB
- Диски:
- 3 × 93 GB SSD на каждом узле YDB
- 20 GB HDD для операционной системы
Тест
Нагрузка на кластер YDB была запущена с помощью команды CLI ydb workload. Дополнительную информацию см. в статье Нагрузочное тестирование.
Чтобы воспроизвести нагрузку, выполните следующие шаги:
-
Проинициализируйте таблицы для нагрузочного тестирования:
ydb workload kv init --min-partitions 1 ydb yql -s 'ALTER TABLE `kv_test` SET ( AUTO_PARTITIONING_MAX_PARTITIONS_COUNT = 2 );'Мы намеренно ограничиваем максимальное количество партиций в таблице
kv_testдо 2 после инициализации. -
Воспроизведите стандартную нагрузку на кластер YDB:
ydb workload kv run mixed -s 600 -t 250 --rate 8000Мы запустили простую нагрузку, используя базу данных YDB как Key-Value хранилище. Точнее, мы использовали нагрузку
mixed, которая одновременно пишет и читает данные, дополнительно проверяя что все записанные данные успешно читаются.Параметр
-t 250используется для запуска нагрузочного тестирования в 250 потоков. Параметр--rate 8000используется для ограничение максимального количества запросов до 8000 запросов в секунду. -
Создайте перегрузку на кластере YDB:
ydb workload kv run mixed -s 600 -t 400Как только первый тест завершился, мы немедленно запустили тот же самый тест в 400 потоков без ограничения максимального количества запросов в секунду, чтобы создать перегрузку.