«Что там с базами, не пора ли добавлять ресурсов?» — казалось бы, звучит как дежурная реплика менеджера, и классический ответ на неё: «всё ок, до конца недели должно хватить!».
На деле этот безобидный на первый взгляд вопрос может быть сигналом о целом ворохе проблем. Важно разобраться, почему его задают (можно ведь посмотреть алерты и мониторинг), о чём именно речь (у нас точно всё ок с архитектурой?), как часто вопрос возникает (сколько денег мы тратим на содержание баз?).
Однажды на вопрос «что там с базами?» мы в команде решили ответить несколько иначе. Вместо «до конца недели должно хватить» — сказали: «давайте мигрируем базы в единый кластер, а тяжёлые файлы перенесём в S3».
О том, что из этого вышло, читайте под катом.
Привет, Хабр! Я Ахмед, заместитель CTO в финансовом маркетплейсе Сравни. Сегодня расскажу историю миграции наших баз данных в кластер и переноса тяжелых файлов в S3; в том числе о том, что пошло не по плану и об обратной стороне размещения баз в едином кластере.
Надеюсь, статья будет полезна разработчикам, которые работают с базами данных и топят за technical excellence, а также продактам и проджектам, желающим быть в теме.
Как мы поняли, что пора
Однажды у нас в Сравни появился новый продукт — кредитный конвейер, автоматизированная система обработки заявок на кредитование и принятия решений. За пару лет система доросла до 13 микросервисов и такого же количества БД. Для каждой БД мы с запасом выделяли ресурсы по CPU, RAM, дисковому пространству, которое заполнялось бешеными темпами.
Продукт делали в режиме честного MVP — когда ради оперативной проверки гипотез и скорой раскатки бизнес-фичей допустимо выбирать не самые оптимальные, но быстрые технические решения. В результате (классика!) архитектура у нас «сложилась исторически».
Например, мы хранили тяжелые файлы непосредственно в БД. Очевидные последствия: файлы копились, базы «пухли», нам то и дело приходили алерты о переполнении той или БД. Приходилось вручную добавлять памяти, что отнимало много времени.
В бэклоге появилась задача — изъять бинарники из БД и хранить их отдельно в S3. Мы решили объединить этот таск с миграцией в единый кластер. Так БД будет удобнее менеджерить, а обслуживание выйдет дешевле. Когда все БД работают в одном кластере, не нужно выделять на каждый отдельный инстанс свои значения по памяти и по процессору. Есть одно общее значение — и базы берут себе, сколько нужно. Это существенная экономия в деньгах: по нашим расчетам, кластер должен обходиться в полтора раза дешевле.
Перенос файлов и миграция: хронология
Поскольку базы содержали множество файлов, мы столкнулись с весьма трудоёмким процессом – нужно было перенести более терабайта данных по сети из одного места в другое.
Как поступили? Сперва анализировали каждую базу на предмет наличия бинарников, а затем все их переносили в S3. Базы становились значительно легче (каждая — на 70%), и это позволяло нам ускорить миграцию в кластер.
Файлы в S3 переносили итерационно: одну унесли — посмотрели, как работает в течение недели; потом за две недели перенести все остальное. На старте постарались выбрать ту БД, которая наименее всего повлияет на клиентский путь.
Последовательность шагов по переносу файлов в S3 была такой:
Добавляем в БД колонку с признаком, где хранится файл (БД или S3). Значение для текущих файлов = БД.
Пишем логику, которая в зависимости от значения признака скачивает файл из БД или S3. То же самое для сохранения файлов.
Включаем сохранение новых файлов в S3.
Создаем джобу, которая в фоне перекладывает существующие файлы из БД в S3 и соответственно меняет значение признака на S3.
Ждем окончания работы джобы. Теперь все файлы перенесены в S3.
Поскольку мы использовали для хранения в БД механизм «large objects» и не использовали lo_unlink, то фактически файлы не удалились из БД. Чтобы они действительно удалились, пользуемся утилитой vacuumlo.
Сначала завершили работу по переносу бинарников в S3 по всем БД, а затем — приступили к миграции БД в единый кластер.
Мигрировали, начиная от самых некритичных баз: их переносили в рабочее время. Миграцию более критичных БД проводили во время наименьшей активности клиентов. На время переноса вешали заглушку, что тот или иной сервис временно недоступен.
Порядок действий по миграции, в свою очередь, был таким:
Создаём новую базу в кластере.
Переводим сервис на реплику боевой базы (реплика всегда в read-only), снимаем дамп pg_dump с мастера.
В новой базе с помощью команды pg_restore восстанавливаем дамп.
Во время исполнения pg_restore пишется лог. Обязательно анализируем лог и в процессе восстановления, и по окончанию.
Если рестор упал, то возвращаем коннект на мастер и идём разбираться, в чём дело.
После успешного pg_restore проверяем, что данные перенеслись без потерь (несколько селектов с получением самых первых и последних записей).
Меняем Connection String на новый, перезапускаем приложение, чтобы сервис подцепил новую БД.
Наши БД устроены по классике: по два инстанса — мастер и слэйв; снимаем бэкапы ежедневно. При этом в ходе миграции никаких бэкапов нам не требовалось, поскольку старая БД не была затронута — и удалялась сильно позднее, когда мы уже были уверены, что миграция прошла успешно.
В целом на перенос каждой базы уходило от одного до нескольких часов — за счёт того, что все тяжёлые файлы были предварительно вынесены в S3. Всего 13 сервисов перенесли за неделю.
Перенос файлов и миграция БД: что может пойти не так
Не обошлось без проблем. Когда мы унесли файлы из первой БД в S3, тестирование показало, что все работает хорошо. Однако после релиза получили свой первый инфаркт: S3 отказывался отдавать нам файлы! Приехали — положили продакшен. Оказалось, дело в банальной невнимательности: подложили на прод тестовый secret.
Ошибку исправили, но осадочек остался. А с ним и паранойя перед следующими итерациями. Поэтому решили действовать осторожно: добавили несколько степеней защиты:
Перехватываем любой эксепшн при чтении.
Перехватываем любой эксепшн при записи.
Делаем пробное подключение к бакету при старте сервера. Если к бакету S3 не получается подключиться, то сервер не поднимется и откатится к предыдущему состоянию.
Меры предосторожности помогли с большей уверенностью перетащить данные из второго сервиса.
Что может пойти не так — вопрос не только про процесс миграции, но и про жизнь после. У размещения БД в едином кластере есть обратная сторона. Если из 10 независимых баз в инстансах переполняется одна, то перестает работать только один сервис. А если все базы расположены в едином кластере, то при переполнении дискового пространства кластера перестают работать все сервисы. Потому что режим read-only и невозможность сохранения вешаются сразу на весь кластер.
Поэтому при при переезде с отдельных инстансов в кластер обязательно нужно слать заблаговременный алерт при достижении определенного порога переполнения БД, чтобы не пропустить момент, когда всё повиснет. В нашем случае алерты приходят при заполнении кластера до 85% и 90% — сигнал о том, что нужно пойти и добавить ресурсов.
Еще одна трудность: чем тяжелее база, тем дольше выполняется дамп и рестор. Важно сделать тестовые замеры этих команд, чтобы понимать итоговое время простоя сервиса — и правильно выбрать техническое окно для проведения работ, оповестить клиентов.
Стоило оно того?
Спустя месяц после переноса файлов в S3 и миграции БД в единый кластер мы получили такие результаты:
Перенос в S3 удешевил затраты на хранение файлов в шесть раз.
Переезд всех инстансов БД в общий кластер снизил затраты на инфраструктуру БД в 1,5 раза.
Доработка системы мониторинга и алертинга во время миграции повысила контроль за стабильностью работы БД (без переезда был риск не так скоро добраться до этих доработок).
Как понять, когда пора мигрировать
В идеальном мире файлы сразу лежат, где полагается, а базы добропорядочно живут в кластерах. В реальном мире есть MVP, технические компромиссы и «так сложилось исторически». Всё это может затянуться — в моей истории продукт прожил пару лет до того, как дело дошло до честной работы с техническим долгом.
Разумеется, проще и дешевле оптимизировать все на ранних этапах, при первых признаках проблемы. Но как понять, что пора мигрировать? Какие в пользу этого могут быть аргументы?
Посмотрите, насколько процентов в день прирастает ваша база. Подойдет любая профильная система мониторинга. Если прирост составляет десятые доли процента в день, то, возможно, базы можно пока не трогать. Если же это процент в день, уже стоит задуматься об улучшениях.
При подготовке процесса стоит учитывать, что и перенос файлов в S3, и миграция БД в кластер обычно не требуют много ресурсов. В нашем случае один разработчик оказался вполне способен в спокойном режиме перевезти один сервис за день.
***
Пора ли переносить файлы из БД в облако? Пора ли мигрировать БД в единый кластер? Как правило, за подобными вопросами кроется ещё один, более глобальный: «Как определить правильный момент, чтобы заняться техническим долгом?». И когда вы в следующий раз услышите: «Что там с базами, не пора ли добавлять ресурсов?» — обратите внимание; возможно, это тот самый момент!
На вопросы о нашем кейсе и о том, как мы в целом работаем с базами данных, с радостью ответим в комментариях.
Комментарии (7)
vagon333
29.08.2024 12:00Если я правильно понял:
- изначально архитектор решил хранить бинарники в базе.
- баз было 2+.
- данных вместе с бинарниками в 1TB???.
Когда базы начали закономерно тупить вы решили:
- перенести бинарники в S3, хостимый в облаке
- объединить все базы на единый сервер или кластер, также хостимый в облаке.
Я бы постеснялся это решение описывать как красивое.
За хранение бинарников в базе архитектора на курсы.
Переход в облако с имеющегося железа - решение для 2014, но не 2024, когда достоинства и недостатки on-prem vs cloud в детских книжках.S3 можно поднять локально, или просто файловое хранилище.
Некоторые базы поддерживают работу с файлами как File Storage - бинарники на диске с контролем из базы.akhsakhmedov Автор
29.08.2024 12:00Спасибо за комментарий!
Вся инфраструктура нашей компании хостится в Облаке, поэтому мы ничего не уносили с железок.
Насчет просчета с хранилищем на старте, даже не буду спорить, я честно описал наш провал )
Наше решение тоже не претендует на роль красивого, оно оптимальное и больше рассказывает как мы проделали работу над ошибками прошлого. И, как мы видим спустя время, не без спотыканий на старте мы справилисьwerter_l
29.08.2024 12:00+1Надеюсь, бэкапы из Облака к себе (локально) вы делаете :)
А то бывали случаи когда и ДЦ сгорали.
AirLight
29.08.2024 12:00Фраза "Перенос в S3 удешевил затраты на хранение файлов в шесть раз" - мало говорит о реалиях, стоимость одного терабайта хранения сейчас может быть несколько тысяч рублей. Стоимость труда программиста для выполнения миграции может быть сильно выше годовой экономии.
NikitchenkoSergey
Молодцы, что справились, конечно. Но мне сама идея хранения файлов в базе кажется очень странной. Подключить s3 сразу сейчас к любому фреймворку очень просто и интересно, почему сразу так не сделали.
akhsakhmedov Автор
Изрядно покопавшись в чертогах разума, так и не вспомнил аргументов к такому решению. И вы абсолютно правы, такое решение было не просто странным, оно было ошибочным. Однако мы ошибок не боимся, признаем их и всегда готовы исправлять
Ivan22
ну бывает, сперва в базу тексты кладут, потом фоточки, а потом понеслась