Меня зовут Сергей Терпугов, я работаю в компании DNS-Технологии в роли TeamLead и активного ментора. Возможно, это прозвучит неожиданно, но я также являюсь нутрициологом и фитнес-тренером. Мне удалось похудеть на 50 килограмм, вырасти с позиции джуна до TeamLead и, как это бывает, «сгореть» на предыдущей работе.
Эта статья – о проблемах, с которыми сталкиваются специалисты при работе с большими данными, и о том, как мы их решаем. Ее структура следующая:
-
Тестовые базы данных. Казалось бы, простая вещь – предоставить каждому разработчику тестовую среду, но на практике возникает множество сложностей. Создание полноценных копий рабочей базы требует огромных ресурсов.
-
Запросы. Работа с запросами в больших базах также имеет свои нюансы и подводные камни.
-
Индексы. Настройка и оптимизация индексов – тема, которую обсуждают часто. Сообщество 1С долгое время испытывало определенные трудности с гибкой настройкой индексов.
-
Мониторинг. Когда у вас множество и очень больших баз данных, их отслеживание и контроль становятся нетривиальной задачей.
Разумеется, перечисленное – это лишь часть проблем и решений. Сегодня мы сосредоточимся именно на этих аспектах.
Нашу основную базу мы называем УБД. Огромная управленческая база размером уже 38 терабайт с MS SQL сервером на борту. Это геораспределенная база по всей России, распределенный РИБ на 10 узлов под каждый регион, огромное количество различных обменов 1С, не 1С, разнородных обменов, со всем чем угодно. И также тысячи пользователей онлайн. Некоторые наши пользователи любят консоль запросов, любят писать запросы и пишут не хуже программистов.
Количество метаданных в нашей базе тоже немалое. Одних только регистров сведений больше полутора тысяч. Если смотреть на топ занимаемого места, то регистр бухгалтерии вход расчетный занимает у нас терабайт почти на основной таблице и индексов 2,6 терабайта. Документ продажи: одна из таблиц в сумме занимает тоже почти 3 терабайта.
Также есть регистры накопления в топе, и опять же еще раз – регистр бухгалтерии в топе. Как вы понимаете, регистр бухгалтерии у нас достаточно огромный.
Проблема организации тестовых баз данных
Первая проблема, с которой мы столкнулись, – это организация тестовых баз данных. Каждому разработчику необходим отдельный контур для разработки и тестирования.
Создание полноценных копий рабочей базы требует огромных ресурсов. Места на диске не напасешься, при этом копирование больших объемов данных сопряжено с дополнительными накладными расходами: требуется время на процесс копирования, свободное дисковое пространство и вычислительные ресурсы. Если же мы сильно урезаем данные, базы становятся слишком маленькими. А маленькие базы сложно использовать для полноценного тестирования. На урезанных базах невозможно корректно протестировать массивные инструменты, поскольку для их работы требуется значительный объем данных.
Решение для тестовых баз. Собственный скрипт
В нашей компании есть специальный отдел – отдел эксплуатации систем. Это специалисты, которые работают на стыке технологий и обладают глубокой экспертизой как в 1С, так и в смежных областях. Это настоящие профессионалы, которые могут ответить на любой технический вопрос, даже если их разбудить посреди ночи.
Эти ребята разработали для нас специальный скрипт на Python, который копирует базу данных из источника в приемник. Скрипт переносит все справочники, справочные сущности, перечисления и планы видов характеристик (ПВХ) в новую базу. Остальные метаданные обрезаются по нескольким фильтрам: те, что содержат периодичность, ограничиваются по временному периоду (например, последние 6 месяцев), а те, где период отсутствует, фильтруются по черным или белым спискам, в зависимости от потребностей конкретного направления или отдела.
Скрипт получился довольно сложным и мощным: он обрабатывает структуру метаданных и копирует огромные объемы данных. Время его работы варьируется от 8 часов до значительно большего срока, в зависимости от требуемых настроек вырезки – кому-то нужна более полная вырезка, кому-то – минимальная.
Скрипт, к сожалению, находится под NDA, поэтому я не могу показать его детали. В упрощенном виде это копирование данных на низком уровне СУБД через прямые SQL-запросы.
Напомню, что наша центральная база занимает 38 терабайт. После копирования с помощью скрипта мы получаем уменьшенную вырезку размером 2,9 терабайта. Это уже неплохой результат, но все еще значительный объем, с которым нужно как-то работать. Как можно улучшить ситуацию дальше?
Решение для тестовых баз. Использование ZFS
Возможно, вы уже слышали о файловой системе ZFS. Помимо своих основных преимуществ, она отлично управляет данными, бережно их эксплуатирует и эффективно хранит и управляет большими массивами дисков, интеллектуально выполняя эти задачи. Помимо всего прочего, ZFS умеет экономить место за счет мощной компрессии и дедупликации, а также создавать снапшоты и клоны этих снапшотов. Вроде бы все отлично, но есть одно «но» – данная система полноценно доступна только под Linux. Она хорошо работает с Solaris и RedHat, но с другими системами дружит не очень.
Тем не менее, существует несколько вариантов ее использования. Мы в своей работе применили два из них. Первый вариант – создание блочных устройств на стороне ZFS и использование их через протокол SCSI для подключения и работы с каталогами, созданными на ZFS. Вроде бы все хорошо, но такой подход создает дополнительную нагрузку на производительность и добавляет еще один слой абстракции: ZFS тратит дополнительные ресурсы на обслуживание этих блочных устройств.
Более интересный для нас вариант – использование MS SQL Server для Linux с размещением каталогов баз данных непосредственно в логических томах ZFS. Это уже гораздо интереснее и с этим можно эффективно работать. К слову, с PostgreSQL ZFS работает «из коробки», то есть не требует никаких дополнительных настроек.
Прежде чем перейти к демонстрации настройки, погружу вас немного в теорию ZFS и далее покажу на простом примере, как легко настроить для работы всю систему ZFS.
Основы ZFS
В системе ZFS есть такое понятие, как Pool. Это контейнер для массивов виртуальных устройств (VDEV), представляющий собой общую абстракцию над физическими дисками. Мы работаем с пулами и именно с них начинаем настройку.
Далее у нас есть понятие VDEV. Это виртуальное устройство, которое состоит либо из одного диска, либо из нескольких дисков, объединенных в массив. Под массивами дисков мы понимаем либо зеркало (mirror), либо какой-то RAID-массив. Существует несколько типов таких массивов, но сейчас мы не будем углубляться в детали. Важно понимать, что VDEV – это либо отдельный диск, либо группа дисков.
Следующее важное понятие – Dataset. Это объект, с которым мы будем непосредственно работать. По сути, это раздел файловой системы ZFS. Проводя аналогию с Windows, датасет можно представить как диск с файловой системой ZFS.
Еще одно ключевое понятие – Snapshot. Это точка восстановления, ссылка или, как еще можно назвать, состояние только для чтения системы на определенный момент времени. Это своего рода сохраненное состояние данных.
Также есть понятие Clone. Если снапшот – это read-only версия, то клон – это модифицируемая копия снапшота. Клон представляет собой уникальную разностную версию снапшота, с которой можно работать.
Настройка ZFS и первые результаты
Теперь перейдем к настройке. Нам для работы потребуется операционная система Linux. Для примера я буду использовать Ubuntu. Устанавливаем инструменты для работы с ZFS с помощью соответствующей команды.
apt install -y zfsutils-linux
Далее создаем простой пул из трех виртуальных дисков. Создаем одно виртуальное устройство (VDEV) типа RAIDZ. Как я уже упоминал, существуют разные варианты конфигурации. В данном случае мы создали дисковый массив RAIDZ.
zpool create storage raidz /vda/vda2 /vda/vda3 /vda/vda4
После этого нам нужно создать датасет – это будет наш раздел. Здесь начинается самое интересное.
zfs create stortage/mssql_dns_m_clone
Чтобы использовать все преимущества ZFS, необходимо выполнить следующие команды.
zfs set atime=off storage/mssql_dns_m_clone
zfs set comression=lz4 storage/mssql_dns_m_clone
zfs set recordsize=64K storage/mssql_dns_m_clone
По умолчанию ZFS, как я уже говорил, очень бережно хранит данные и отслеживает все изменения, и чтения в том числе, происходящие с ними. В рамках тестовой среды такое тщательное отслеживание может быть избыточным. Поэтому мы можем отключить его с помощью команды `atime=off` и получить прирост производительности. Метадата обращения к данным при этом фиксироваться не будет, что в тестовой среде и не критично.
Чтобы задействовать мощное сжатие и дедупликацию, нам нужно включить параметр сжатия `compression=lz4` и установить размер блока 64 килобайта. Что мы получаем после выполнения этих настроек? Вспомним, что наша база занимала 2,9 терабайта – именно столько показывает Windows. Однако фактически на диске она занимает всего 835 гигабайт.
Это уже неплохой результат – мы значительно уменьшили занимаемое базой место. Фактически мы используем 835 гигабайт. Но можно улучшить результат еще больше.
Создание снапшотов и клонов ZFS
Как я уже упоминал, ZFS умеет создавать снапшоты и клоны. Давайте применим эту технологию на практике и посмотрим, что получится.
Создаем снапшот и называем его, например, Factory. Это точка восстановления нашего текущего состояния.
zfs snapshot storage/mssql_dns_m_clone@factory
Далее клонируем этот снапшот, указывая новое место для размещения.
zfs clone storage/mssql_dns_m_clone@factory storage/mssql_dns_m_clone1
По сути, мы создаем новый датасет, с которым можно работать. Применяем к этому датасету уже знакомые нам настройки ZFS, и все готово.
Этап подключения и настройки MS SQL Server мы опустим, так как это достаточно стандартная процедура. Базу можно присоединить либо через консоль управления, либо с помощью скрипта. На весь процесс уходит около 5 минут. Создание снапшота и клонирование – это очень быстрые и ресурсоэффективные операции.
В результате 835 гигабайт превращаются в новую базу размером всего 19 мегабайт. Это полноценная среда, которую можно выдать разработчику для работы или использовать как тестовую среду для заказчиков. Такой клон является полноценной версией, которая будет накапливать в себе изменения. Конечно, со временем его размер будет расти. Но главное преимущество в том, что мы можем в любой момент быстро пересоздать такую тестовую среду.
В итоге у нас появилась компактная вырезка, содержащая необходимые для тестирования метаданные – все в точности, как мы планировали. Объем занимаемого места значительно сократился. Мы получили возможность создавать снимки датасетов и мгновенно генерировать новые копии баз данных быстро и экономно.
Эту вырезку мы обновляем примерно раз в два месяца. Для наших целей этого вполне достаточно.
Проблема работы с запросами и ее решение. Ограничение ресурсов и реплики
Запросы – это основа всей работы. Без них невозможно построить никакую аналитику или отчеты. Можно сказать, что все в нашей системе работает на запросах.
При разработке в тестовой среде можно столкнуться с проблемой: запрос, который отлаживается локально, при переносе на продуктивную среду может выполняться чрезвычайно долго или вообще «повесить» систему. Чтобы понять масштаб проблемы, достаточно выполнить простой запрос, например, `ВЫБРАТЬ КОЛИЧЕСТВО(*)`. Здесь нас может ждать сюрприз: из-за большого объема данных выполнение может занять от 1,5 до 17 минут. Обычный запрос на подсчет количества строк может «зависнуть» на 17 минут.
Помимо стандартных возможностей нашей консоли запросов (кстати, она умеет выполнять запросы в фоновом режиме), есть еще один важный фактор. Кроме разработчиков, которые создают и тестируют запросы, у нас есть пользователи, активно использующие консоль запросов. Они тоже пишут запросы, проверяют свои модели и регулярно нагружают систему. С этим нужно как-то жить. Постоянно ждать завершения долгих запросов – не вариант.
Что мы делаем для решения этой проблемы? Во-первых, наша консоль умеет "отстреливать" пользователей, которые превышают заданные лимиты. Постоянно отслеживается, какой пользователь превышает лимит по времени или по объему памяти, выделяемой под запрос. Если лимит превышен, такой запрос автоматически прерывается.
Кроме того, консоль умеет выполнять запросы в фоновом режиме – функция, которая сейчас уже не кажется чем-то удивительным. Мы также придумали способ выполнять тяжелые запросы не на основной (мастер) системе, а на реплике базы данных. Для этих целей мы выделили отдельный рабочий сервер. На нем настроили правила назначения функциональности таким образом, чтобы весь код из определенного модуля направлялся на этот конкретный сервер. Далее на этом сервере мы заменили адрес подключения с мастер-базы на реплику. В результате запросы, выполняемые из определенного модуля, направляются на рабочий сервер и уже с него уходят в реплику. Таким образом, мы разгружаем основную систему, перекладывая нагрузку на реплику.
Отчеты и инструменты, которые не требуют мгновенной актуальности данных, могут спокойно работать с репликой. Некоторые запросы также можно направлять туда. Причем этим процессом можно управлять прямо из консоли запросов.
Проблема индексов и ее решение: Ручная настройка на уровне СУБД (запрещенка)
До недавнего времени у нас были серьезные проблемы с индексами. Эта проблема касалась не только крупных баз, но, вероятно, всего сообщества 1С в целом. Основные трудности заключались в ограниченности настроек, отсутствии гибкости управления и невозможности создания произвольных индексов.
К сожалению, все эти проблемы действительно существовали. На больших базах они проявлялись особенно остро, поскольку стандартные средства, такие как установка галочки «Индексировать», не всегда позволяли решить возникающие задачи. С этим приходилось как-то жить.
Как мы справлялись с этой ситуацией? Здесь я должен предупредить: уберите детей от экранов, сейчас будет «страшная запрещенка».
Из-за огромного объема данных нам приходилось в редких случаях использовать настройку индексов напрямую через SQL. Мы создавали индексы средствами SQL: разработали небольшой инструмент, позволяющий настраивать индексы по нашему усмотрению, реализовали небольшую форму и использовали этот подход в чрезвычайных ситуациях.
Дело в том, что не всегда удавалось решить проблему стандартными средствами индексирования. Смена полей – это отдельная, сложная тема, а реструктуризация могла быть просто устрашающей. Мы получили возможность задавать произвольный порядок ключей индекса и создавать индексы с включенными полями – то есть делали именно то, что было необходимо. В некоторых ситуациях это нас очень выручало, особенно в периоды пиковых нагрузок, например, в новогодние праздники, когда нагрузка достигала колоссальных значений.
При реструктуризации все эти индексы, конечно же, удалялись. Этот процесс занимал очень много дополнительного места и на самом деле мог нарушить процесс реструктуризации (v2). Однако в некоторых экзотических ситуациях мы все же применяли этот метод.
Сейчас в новых платформах, начиная с версии 8.3.26, появился отличный механизм, который мы будем использовать. Больше нам, к счастью, не придется прибегать к таким радикальным мерам.
Проблема мониторинга и ее решение: Использование специализированных инструментов
Здесь тоже нас подстерегают определенные сложности. Стандартные средства мониторинга, имеющиеся в нашем распоряжении, практически не справляются с задачей.
Журнал регистрации, например, становится огромным и очень медленным. Легко «повесить» базу – достаточно пары неправильных настроек, и база уходит в состояние глубокой задумчивости (или «в астрал»), а агент сервера может просто упасть. Это неприятно. Технологический журнал – вещь мощная, генерирует огромное количество данных, буквально все. Из него можно получить любую информацию, но мониторить его вручную крайне сложно. Нужно быть экспертом по регулярным выражениям или обладать сверхъестественным зрением.
Без визуализации разобраться в этом потоке текста практически невозможно.
Мы выгружаем все возможные данные в OpenSearch – журналы регистрации, технологические журналы, все грузим полностью.
Мы заменили стандартную форму получения данных журнала регистрации на собственную, чтобы получать информацию напрямую из OpenSearch и агрегировать в 1С всю необходимую информацию. Для работы с данными из технологических журналов мы используем Graylog и Kibana, а для визуализации – Grafana.
Так выглядит наш журнал регистрации. По сути, он ничем не отличается от стандартного, за исключением одной детали. Просто добавлена плашка, указывающая, что данные получены из OpenSearch. Kibana – это прекрасный инструмент, позволяющий фильтровать, визуализировать данные и накладывать различные фильтры для анализа технологического журнала.
И, конечно же, Grafana. Без нее – никак. Дашборды, созданные в Grafana, можно передать заказчикам или бизнес-блокам, чтобы они могли самостоятельно отслеживать метрики и оперативно реагировать на изменения. Всю информацию можно удобно визуализировать и анализировать.
Graylog является аналогом Kibana, но мы используем его специально для работы с журналом регистрации.
Перечисленное в статье – это лишь малая часть того, что мы используем и делаем в своей работе, и круг проблем на этом не заканчивается. Но ведь проблемы – это и есть наш рост, наши точки развития. Я хочу пожелать вам прекрасных, интересных задач и проблем, которые будут толкать вас вперед и помогать расти профессионально.
*************
Статья написана по итогам доклада (видео), прочитанного на конференции INFOSTART TECH EVENT.
Вступайте в нашу телеграмм-группу Инфостарт