VictoriaLogs: система логирования для больших объёмов данных

от автора

Адаптированный обзор по мотивам статьи «VictoriaLogs Deep Dive: Rethinking Log Management for the Petabyte Era».

VictoriaLogs — система хранения и поиска логов от команды VictoriaMetrics. Её идея проста: не заставлять оператора заранее проектировать индексы и схему данных, а дать ему возможность принимать логи и искать по их полям сразу. При этом система должна оставаться относительно простой и на одном сервере, и в кластере.

Схема архитектуры VictoriaLogs

Схема архитектуры VictoriaLogs

Ниже — разбор того, за счёт чего VictoriaLogs пытается решить типичные проблемы систем логирования и в каких случаях на него стоит смотреть внимательнее.

Почему логи всё ещё сложно хранить

Логи есть у любого приложения: их пишут сервисы, базы данных, API-шлюзы, балансировщики и кластеры Kubernetes. По ним восстанавливают ход инцидента: что именно случилось, когда и с каким запросом или пользователем это связано.

На практике система логирования нередко становится отдельным тяжёлым сервисом. По мере роста объёма приходится планировать индексы и шарды, следить за потреблением памяти, ограничивать срок хранения, ждать долгих запросов и платить за всё большее хранилище. Особенно неудобны поля с высокой кардинальностью — то есть с большим числом уникальных значений: trace_id, request_id, user_id, IP-адреса. Именно они часто нужны при расследовании, но для многих систем дороги в индексе.

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

Чем он отличается от привычных вариантов

Elasticsearch — поисковый движок общего назначения, который часто используют для логов. На больших объёмах его эксплуатация обычно включает управление жизненным циклом индексов, планирование шардов, настройку памяти, правил сопоставления полей (mapping) и балансировку кластера.

Grafana Loki уменьшает стоимость индексирования, опираясь на потоки и метки. Такой подход хорош для многих сценариев, но требует аккуратно выбирать метки: если в них попадают trace_id или user_id, число уникальных значений быстро становится проблемой.

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

VictoriaLogs не пытается быть универсальной СУБД. Это хранилище, спроектированное именно для логов: оно автоматически делает поля доступными для поиска и не требует заранее описывать схему.

Что настраивать не нужно

Перед началом работы не требуется создавать индексы, описывать схему или задавать правила mapping. Достаточно отправить записи, например:

{  "service":"payments",  "user_id":"12345",  "trace_id":"xyz",  "status":"failed"}

После приёма по полям такой записи можно выполнять запросы. Это не отменяет здравого смысла в именовании полей и выборе формата логов, но избавляет от ситуации, когда нужное во время инцидента поле оказалось не предусмотрено индексом.

Один бинарный файл — от одного узла до кластера

VictoriaLogs поставляется одним исполняемым файлом. В небольшом развёртывании он работает как одиночный сервер. В кластере тот же бинарный файл выполняет одну из трёх ролей:

  • vlinsert принимает входящие логи;

  • vlstorage хранит данные;

  • vlselect обрабатывает запросы.

Один бинарный файл VictoriaLogs в односерверном и кластерном режимах

Один бинарный файл VictoriaLogs в односерверном и кластерном режимах

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

Как устроено хранение

VictoriaLogs использует колоночный подход. В строковом хранении запись лога лежит целиком рядом с остальными полями той же записи. В колоночном хранении значения каждого поля располагаются отдельно:

service---------checkoutpaymentsinventorystatus---------successfailedsuccessuser_id---------123456789

Если запросу нужно найти только service="payments", необязательно читать все поля каждой записи. Достаточно обратиться к данным нужного поля и к служебным структурам, которые позволяют отсеять неподходящие блоки. Меньше чтений — меньше I/O и быстрее ответ на запрос.

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

Какие оптимизации помогают запросам

В хранилище сочетается несколько приёмов.

  • Фильтры Блума позволяют исключить блок, в котором искомого значения заведомо нет. Они сокращают лишние чтения, хотя положительный результат фильтра ещё не доказывает наличие значения.

  • Специализированные кодировки используются для значений, у которых есть подходящая структура: IP-адресов, чисел и меток времени. Это помогает одновременно хранить данные компактнее и быстрее их читать.

  • Локальность потоков означает, что записи одного потока размещаются рядом. Это улучшает сжатие, фильтрацию по потоку и эффективность кэша.

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

Эти механизмы не избавляют от необходимости проверять систему на собственных данных. Но они объясняют, почему VictoriaLogs ориентирован на дешёвый поиск по большим объёмам логов, а не только на быстрый приём записей.

Высокая кардинальность и расследование инцидентов

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

Панель ошибок      ↓Сервис      ↓Пользователь или trace_id      ↓Конкретный запрос

VictoriaLogs делает такие поля доступными для поиска без предварительного проектирования индекса. Это одно из его главных отличий для оператора: вопрос «мы вообще индексировали это поле?» не должен возникать в середине инцидента.

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

LogsQL: язык запросов для работы с логами

В VictoriaLogs используется язык запросов LogsQL. Его логика близка к обычной работе с логами: сначала отобрать записи, затем преобразовать результат или посчитать агрегаты.

Простейший запрос найдёт ошибки за последние пять минут:

_time:5m level:="error"

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

_time:5m level:="error"| count()

Можно посчитать долю ошибок по сервисам и оставить только те, у которых она выше 5 %:

* | stats by (service)    count() as total,    count() if (log_level:="error") as errors| math errors * 100 / total as error_rate| error_rate:>5

Такой синтаксис удобен для типовых эксплуатационных задач: поиска, фильтрации, группировки и расчёта показателей по логам.

Оповещения и метрики из логов

Логи полезны для разбора уже случившейся проблемы. Чтобы реагировать раньше, статистику запросов LogsQL можно передать в vmalert, а уведомления — в Alertmanager:

VictoriaLogs      ↓Статистика LogsQL      ↓vmalert      ↓Alertmanager      ↓Slack / PagerDuty / электронная почта

Зоны ответственности здесь разделены: VictoriaLogs выполняет запрос и выдаёт статистику, vmalert проверяет условия правил, Alertmanager маршрутизирует уведомления.

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

Логи ↓Агрегации ↓Метрики временных рядов ↓VictoriaMetrics

Как масштабируется VictoriaLogs

На одном сервере VictoriaLogs подходит для небольшого или среднего объёма данных. Когда одного узла недостаточно, приём, хранение и выполнение запросов можно масштабировать независимо:

  • добавить vlinsert, если не хватает скорости приёма;

  • добавить vlstorage, если растёт объём хранения;

  • добавить vlselect, если запросов становится больше или они тяжелее.

Это позволяет перейти к кластерной схеме без смены модели работы с логами. Однако решение о кластере всё равно требует обычного эксплуатационного проектирования: оценки отказоустойчивости, резервного копирования, срока хранения и стоимости инфраструктуры.

Когда VictoriaLogs имеет смысл рассматривать

VictoriaLogs стоит оценить, если вы эксплуатируете Kubernetes или распределённые сервисы, хотите долго хранить логи, часто ищете по trace_id, request_id или user_id и не хотите поддерживать сложную схему индексов только ради этой задачи.

Система будет менее очевидным выбором, если первична произвольная SQL-аналитика по данным, не являющимся логами. В таком сценарии стоит сравнить её с ClickHouse и другими аналитическими СУБД.

Главное, что следует проверить на собственном стенде: скорость приёма, объём данных на диске после сжатия, задержку нужных запросов, сценарии отказа и стоимость кластера. Именно эти цифры, а не общие обещания, покажут, подходит ли VictoriaLogs конкретной команде.

ссылка на оригинал статьи https://habr.com/ru/articles/1068892/