Исправляем OOM-ошибки приложений Apache Kafka Streams через конфигурирование RocksDB

Автор Категория ,
Исправляем OOM-ошибки приложений Apache Kafka Streams через конфигурирование RocksDB

Сегодня заглянем под капот stateful-приложений Kafka Streams и рассмотрим, что такое RocksDB, как устроено это key-value NoSQL-хранилище и почему его необходимо настраивать для быстрой и безотказной работы приложений потоковой аналитики больших данных. Читайте далее, какие проблемы приложений Kafka Streams связаны с RocksDB и как ограничить повышенное потребление оперативной памяти.

Что такое RocksDB и при чем здесь Apache Kafka Streams

Для создания распределенных приложений, которые будут обрабатывать данные, хранящиеся в топиках Apache Kafka, используется специальный компонент этой платформы потоковой передачи событий – клиентская библиотека Kafka Streams. Приложение Kafka Streams может выполнять операции без сохранения состояния (stateless), такие как map и фильтрация, а также операции с отслеживанием состояния (stateful): оконные соединения и агрегаты для входящих записей данных. Для stateful-операций Kafka Streams использует локальные хранилища состояний, отказоустойчивость которых обеспечивается за счет связи с логом изменений, хранящимся в Kafka. В качестве хранилища состояний по умолчанию Kafka Streams использует RocksDB – адаптируемое, встраиваемое и постоянное key-value хранилище [1].

Эта высокопроизводительная встраиваемая NoSQL-СУБД была написана разработчиками Facebook в 2012 году на C++ на основе LevelDB от Google. Сначала open-source проект был выпущен под лицензией BSD, а в июле 2017 года перенесен на лицензию Apache 2.0. RocksDB оптимизирована для многоядерных CPU, рабочих нагрузок ввода/вывода (I/O) и эффективного использования быстрой памяти, в частности, твердотельных SSD-накопителей. Надежность и быстрота работы RocksDB обеспечиваются следующими решениями [2]:

  • журнально-структурированное дерева со слиянием (LSM tree);
  • префиксы ключей для сокращения объема считываемых данных;
  • механизм контрольной суммы для блока данных с аппаратной поддержкой;
  • лог транзакций с механизмом пакетной фиксации;
  • балансировка нагрузки через логическое разделение данных;
  • LRU-кэширование и табличные кэши;
  • изначальная ориентация на работу с большими объемами данных;
  • фокус на «быстрые» носители данных (SSD-накопители и флэш-диски).

Facebook, Yahoo!, LinkedIn и многие другие компании используют RocksDB в своей инфраструктуре для обеспечения высокой производительности обслуживания данных. Также RocksDB часто применяется как механизм хранения в рамках более крупной СУБД, например, в CockroachDB [2]. А Kafka Streams приложениях RocksDB выполняет роль хранилища состояний, оптимизированного для записи. Поэтому именно RocksDB может быть источником некоторых проблем с приложениями Kafka Streams, о чем мы поговорим далее.

4 проблемы приложений Kafka Streams из-за RocksDB и способы их решения

Основными проблемами приложений Kafka Streams вызванными некорректной работой RocksDB, можно назвать следующие [1]:

  • повышенное потребление памяти;
  • чрезмерное использование дискового пространства;
  • большое количество операций дискового ввода-вывода и остановки записи;
  • слишком много открытых файлов.

Что представляет собой каждая проблема и как решить ее с помощью грамотного конфигурирования RocksDB, мы рассмотрим далее.

Нехватка памяти

Если приложение Kafka Streams потребляет слишком много памяти из-за хранилища состояний, оно работает медленно или даже вылетает из-за ошибок OutOfMemory. Инструменты мониторинга операционной системы показывает высокий уровень использования памяти, а следующие метрики в Kafka Streams (версии платформы 2.7 и выше) принимают слишком большие значения [3]:

  • size-all-mem-tables – размер активных неизменяемых таблиц memtables в байтах;
  • block-cache-usage – размер памяти для записей в кэше блоков (байт);
  • block-cache-pinned-usage – размер памяти в байтах для записей, закрепляемых в блочном кэше;
  • estimate-table-readers-mem – предполагаемая память в байтах, используемая для чтения таблиц сортированной последовательности (Sorted Sequence Tables, SST), кроме памяти в блочном кэше.

Если хранилище состояний состоит из нескольких экземпляров RocksDB, как в случае агрегации по времени и сеансовых окон, каждая метрика суммирует значения со всех экземпляров RocksDB, кроме метрик блочного кэша (block-cache- *). Метрики блочного кэша суммируют значения со всех экземпляров RocksDB, если каждый из них использует свой собственный блочный кэш. А если кэш одного блока является общим для всех экземпляров, то эти метрики покажут значение только для одного экземпляра.

Решить проблему с чрезмерным потреблением памяти можно следующими способами:

  • проверить соответствие фактического размера хэш-таблицы memtable заданному в Kafka Streams. Настроить эту конфигурацию можно в реализации RocksDBConfigSetter через методы options.setMaxWriteBufferNumber() и options.setWriteBufferSize().
  • использовать общий блочный кеш во всех хранилищах состояний RocksDB, которые работают в одном клиенте Kafka Streams. Можно ограничить память, используемую совместно блочным кэшем и хэш-таблицами memtables.
  • проверить типовые ошибки RocksDB, которые связаны с памятью и могут быть исправлены в новой версии или с помощью рекомендации профессионального сообщества. Например, как исправить ошибку с утечкой памяти при применении операции drop() к семейству столбцов или как обойти исключение, сгенерированное неверным выделением памяти при использовании оператора сравнения ASSERT_NE в рамках тестирования с Google Testing Framework [4].

Завтра мы продолжим разговор про то, как настройки RocksDB влияют на работу stateful-приложений Apache Kafka Streams и рассмотрим особенности конфигурирования дисковых операций в этом NoSQL-хранилище данных.

Больше деталей по разработке распределенных приложений потоковой аналитики больших данных с Apache Kafka и администрированию кластеров вы узнаете на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:

Источники

  1. https://www.confluent.io/blog/how-to-tune-rocksdb-kafka-streams-state-stores-performance/
  2. https://ru.bmstu.wiki/RocksDB
  3. https://docs.confluent.io/platform/current/streams/monitoring.html
  4. https://github.com/facebook/rocksdb/issues