Допустим, база занимает 400 ГБ, а на первую передачу на резервную площадку в другой стране есть ночное окно в шесть часов. Первая мысль простая: 400 ГБ — это примерно 3 200 гигабит, порт у сервера на 1 Гбит/с, значит около 3 200 секунд, то есть чуть меньше часа. Шесть часов выглядят щедро, можно даже не торопиться.
Такой расчёт приятен и почти всегда неверен. Он отвечает на вопрос «за сколько байты пролетели бы по идеальной трубе», а нас интересует, когда на другом конце появится база, с которой можно работать. Между этими вопросами лежит несколько этапов, и каждый из них добавляет своё время. Ниже разберём их по порядку и в конце сложим в одну цифру. Все числа в статье условные: они нужны, чтобы показать ход расчёта, а не чтобы предсказать ваш результат.
Скорость порта и скорость, которую вы реально получите
Цифра в описании порта — это потолок физического интерфейса. Реальная скорость одной передачи между двумя странами определяется самым узким местом на всём пути, и порт часто оказывается не им. Что обычно ограничивает:
- Задержка и окно TCP. Один TCP-поток на большом расстоянии упирается в соотношение окна и времени оборота пакета. Чем длиннее маршрут, тем меньше данных одна сессия может держать «в полёте» без подтверждения. Поэтому один поток через континент нередко работает заметно медленнее, чем несколько параллельных.
- Потери и перегрузка на маршруте. Даже небольшая доля потерянных пакетов заставляет TCP снижать скорость, и на длинной дистанции он восстанавливается медленнее.
- Диск отправителя. Если база читается с того же тома, на котором идёт рабочая нагрузка, копия конкурирует с запросами пользователей. Отдавать вы сможете ровно столько, сколько диск даёт сверх текущей нагрузки.
- Шифрование и сжатие. Туннель или SSH-канал расходует процессор. На небольшом VPS с одним-двумя vCPU шифрование потока может стать узким местом раньше сети.
- Диск получателя. Запись на принимающей стороне тоже должна успевать, причём не только данные, но и последующая проверка.
Отсюда первое практическое правило: в формулу подставляется не скорость порта, а полезная скорость, измеренная на этом же маршруте, этим же инструментом и желательно в то же время суток, когда пойдёт копирование. Для замера не нужна вся база. Достаточно отправить на резервную площадку файл в несколько гигабайт тем способом, которым вы будете отправлять копию, и посмотреть среднюю скорость за несколько минут устойчивой передачи, а не пиковую в первые секунды.
Допустим, замер показал 35 МБ/с, то есть около 280 Мбит/с. Это всего 28% от номинального гигабита, и ничего необычного в этом нет. Тогда 400 ГБ (примем 400 000 МБ) передаются за 400 000 / 35 ≈ 11 430 секунд, то есть около 3,2 часа. Мы уже втрое отошли от «почти часа», а это только сама передача.
До первого байта и после последнего: подготовка, сжатие, проверка
Копию нужно сначала получить. Здесь многое зависит от того, что именно вы копируете. Для PostgreSQL pg_basebackup создаёт базовую копию работающего кластера: она охватывает файлы всего кластера и подходит как для восстановления, так и для подготовки standby. Это иной уровень, чем логический экспорт одной базы: в копию попадает весь кластер целиком, со всеми базами внутри, а значит, и размер для расчёта нужно брать у кластера, а не у самой важной из баз.
Разница не только в объёме. Логический экспорт — это чтение и сериализация данных, а на принимающей стороне после него придётся заново загружать строки и строить индексы. Файловая копия кластера передаётся крупнее, зато на получателе её не надо «собирать» заново. Для расчёта времени это два разных сценария, и смешивать их в одной формуле нельзя.
Теперь про сжатие. Оно меняет объём, который пойдёт по сети, но платит за это процессором с двух сторон. Выигрыш зависит от данных: текстовые таблицы и JSON сжимаются хорошо, уже сжатые или зашифрованные значения, а также бинарные вложения почти не уменьшаются. Поэтому закладывать коэффициент сжатия «из головы» не стоит: возьмите кусок реальных данных, сожмите и сравните размеры. Ещё важнее вот что: если сжатие идёт в один поток на слабом процессоре, оно может выдавать, например, 60–80 МБ/с, а это быстрее нашей сети в 35 МБ/с, и тогда сжатие выгодно. Но если процессор выдаёт 20 МБ/с, оно само превращается в потолок. Конвейер «прочитать — сжать — зашифровать — отправить — принять — записать» идёт со скоростью самой медленной ступени.
И, наконец, проверка. Передача без ошибок ещё не доказывает, что копия пригодна. Перед тем как считать копию состоявшейся, имеет смысл хотя бы сверить контрольные суммы или размеры файлов, а лучше — проверить, что кластер на получателе действительно стартует. Контрольные суммы требуют повторного чтения всего объёма на принимающем диске. Если диск читает 200 МБ/с, то для 400 ГБ это 2 000 секунд, около 33 минут. Это ещё один этап, который не видно в делении гигабайтов на мегабиты.
Для restic, если вы храните копии как снимки, логика похожа: восстановление позволяет извлечь выбранный снимок в отдельную директорию, и в этом есть практический смысл — сначала проверить результат там, не трогая рабочие данные. Тут же полезно помнить различие фильтров: --path выбирает снимок, а --include и --exclude ограничивают извлекаемые файлы. Это не одно и то же, и ошибка в понимании может привести к тому, что вы проверите не тот снимок или не тот набор файлов.
Пока копия ехала, база не стояла
Самая коварная часть расчёта — изменения. Основная база продолжает принимать записи все 3,2 часа передачи, плюс время подготовки и проверки. К моменту, когда последний байт снимка доехал, копия уже устарела: она отражает состояние на момент начала. Чтобы получить актуальную реплику, нужно доставить и применить всё, что накопилось с тех пор.
В PostgreSQL эти изменения идут через журнал предзаписи (WAL). В описании warm standby есть два положения, которые прямо влияют на наш расчёт. Первое: пропускная способность канала должна превышать скорость образования WAL. Если журнал производится быстрее, чем канал успевает его вывозить, реплика не догонит основной сервер никогда, сколько бы вы ни ждали. Второе: после отключения реплике требуется догнать основной сервер — то есть любой обрыв связи добавляет к отставанию время на догон.
Это превращает расчёт в задачу о догоняющем. Пусть в течение рабочего дня база порождает в среднем 6 ГБ WAL в час, то есть около 1,7 МБ/с, а в часы пиковой нагрузки, скажем, 25 МБ/с. При нашей полезной скорости 35 МБ/с запас в среднем получается большой, а в пик — всего 10 МБ/с. Догонять мы можем со скоростью разницы между пропускной способностью и скоростью образования журнала:
время догона = накопленный объём / (полезная скорость − скорость образования WAL)Если снимок готовился и ехал 4 часа в среднем режиме, накопилось 4 × 6 = 24 ГБ журнала. Скорость догона в среднем режиме: 35 − 1,7 ≈ 33,3 МБ/с. Тогда 24 000 / 33,3 ≈ 720 секунд, то есть около 12 минут. Приятно. Но если те же 4 часа пришлись на ночную пакетную обработку с повышенной записью, объём журнала и скорость его образования окажутся совсем другими, и догон растянется. Если же скорость образования WAL приблизится к полезной скорости канала, знаменатель стремится к нулю, а время догона — к бесконечности. Вот почему запас по каналу нужен не для красоты: догоняющей реплике нужна пропускная способность с заметным превышением, а не равенство.
Ещё одно следствие: окно передачи лучше выбирать не по календарю, а по графику записи. Ночью, когда основная нагрузка стихает, и канал свободнее, и журнал растёт медленнее. Но ночные задачи — выгрузки, пересчёты, обслуживание таблиц — иногда создают как раз всплеск записи. Это стоит проверить по реальной статистике своей базы, а не предполагать.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.
Отставание — это не то же самое, что потеря данных
Здесь легко запутаться в терминах, поэтому разведём два понятия. Время копирования — сколько уйдёт на то, чтобы первая полноценная копия оказалась на резервной площадке. Допустимая потеря данных (RPO) — за какой период изменений вы готовы заплатить, если основная площадка исчезнет прямо сейчас. Первое — разовая величина настройки, второе — постоянное свойство работающей схемы.
После того как реплика догнала основной сервер и переключилась в режим непрерывной передачи, её отставание — это уже не часы, а секунды или минуты, и именно оно определяет RPO. По описанию warm standby, при асинхронной передаче WAL остаётся окно потери ещё не переданных изменений: подтверждённая клиенту транзакция может не успеть доехать до резерва. Синхронная фиксация, напротив, может ожидать подтверждения от standby, и тогда окно потери сжимается, но каждая запись становится зависимой от задержки между странами. Во что это обходится по миллисекундам, мы разбирали отдельно: реплика базы в другой стране и цена синхронной записи.
Практически это значит, что у вас два независимых числа, и оба нужно сравнить с требованиями бизнеса:
| Показатель | Что измеряет | От чего зависит |
|---|---|---|
| Время первой доставки копии | Сколько часов до момента, когда на резерве есть база и она догнала основной сервер | Объём, полезная скорость, подготовка, проверка, поток изменений |
| Отставание реплики (основа для RPO) | Сколько последних изменений можно потерять при аварии | Режим передачи WAL, канал, нагрузка записи, обрывы связи |
Полезный приём: сформулировать допустимое отставание в единицах, которые можно измерить. Например, «не больше пяти минут изменений». Тогда становится понятно, что считать нарушением, а канал и режим передачи можно подбирать под эту цифру. Фраза «хотим минимальные потери» ничего не говорит и ничему не помогает.
Заметим и обратную связь. Любой обрыв линка между площадками увеличивает отставание, а потом запускает догон по тому же уравнению, что мы разбирали выше. Если у вас маршрут иногда пропадает на полчаса, то и RPO в эти полчаса вырастает до этих же тридцати минут, как бы красиво ни выглядела средняя цифра. Поэтому запас по каналу нужно оценивать как способность быстро восстановиться после такого провала, а не только как возможность тянуть средний поток.
Сравнение маршрутов: что менять, если время не устраивает
Если итоговая цифра не вписывается в окно, есть несколько рычагов, и они действуют по-разному. Вот как можно сравнить варианты на нашем условном примере (400 ГБ, измеренная полезная скорость 35 МБ/с):
| Что меняем | На что влияет | Что проверить замером |
|---|---|---|
| Несколько параллельных потоков вместо одного | Полезная скорость на длинной дистанции | Растёт ли суммарная скорость и не упирается ли процессор |
| Сжатие данных | Объём по сети, но нагрузка на CPU обеих сторон | Реальный коэффициент на ваших данных и скорость сжатия |
| Другая локация резерва | Задержка и качество маршрута | Тестовая передача в нужное время суток |
| Копия с реплики, а не с основного сервера | Нагрузка на рабочую базу | Свободная скорость чтения диска у источника |
| Предварительная копия, затем только изменения | Короткое финальное окно | Скорость образования журнала за время подготовки |
Обратите внимание: ни один рычаг не даёт линейного эффекта по умолчанию. Удвоение потоков не удваивает скорость, а сжатие не уменьшает объём вдвое. Особенно осторожно стоит экстраполировать результат пробной передачи на большие объёмы. Тест в 5 ГБ может показать устойчивые 35 МБ/с, а на 400 ГБ маршрут сменит загрузку, провайдер где-нибудь ограничит долгую сессию, диск исчерпает кратковременный запас производительности, и средняя скорость упадёт. Поэтому оценка на больших объёмах — это диапазон, а не точка. Разумная привычка: считать по нижней трети измеренных значений и добавить запас, а затем подтвердить расчёт реальной передачей хотя бы части объёма достаточной длительности.
Если ресурсы на стороне резерва вы подбираете под эту задачу, полезно мыслить от узких мест. Для принимающего VPS важны диск (на нём одновременно идёт запись, а потом проверка и восстановление), процессор (распаковка, шифрование, применение журнала) и свободное место: копия и распакованные файлы, а иногда и накопленный журнал должны поместиться одновременно. В публичном предложении VPS MAATRIX перечислены локации UK, US, RU и FR, а серверы работают на NVMe и AMD EPYC с root-доступом. Тарифы, например Ba (1 vCPU, 2 ГБ RAM, 40 ГБ NVMe) или Maat (8 vCPU, 16 ГБ, 240 ГБ), отличаются именно такими ресурсами, но они остаются отправной точкой: подойдёт ли конкретный тариф под ваш объём, показывает только тест на вашей нагрузке. Для базы в 400 ГБ из нашего примера объём диска в 40 или 80 ГБ очевидно не подходит, и это тот случай, когда арифметику стоит сделать до заказа, а не после.
Восстановление на получателе — отдельная строка расчёта
Наконец, самый частый пропуск. Когда последний байт доехал, а журнал догнан, у вас есть файлы. Но база, которая отвечает на запросы, появляется не сразу. Всё зависит от того, что именно лежит на резерве.
Если на получателе работает реплика в режиме standby, то после догона она уже содержит актуальные данные, и переключение на неё — это короткая операция, а основное время ушло на предыдущие этапы. Но если на резервной площадке хранится копия в виде архива или снимка, то в момент аварии нужно ещё распаковать или извлечь данные, поднять кластер, дождаться, пока он проиграет журнал до нужной точки, и проверить работоспособность. Это время нужно измерить отдельно, на пробном восстановлении, а не оценивать «по ощущениям». Именно в такой пробе полезно использовать извлечение в отдельную директорию: так вы проверяете копию и не рискуете живыми данными.
Восстановление не обязано быть быстрее передачи. Распаковка сотен гигабайт, запись мелких файлов, проигрывание накопленного журнала — всё это ограничено диском и процессором получателя. Поэтому время восстановления лучше считать по тому же принципу: объём делим на измеренную скорость этапа, а не на паспортные характеристики диска. И вновь не стоит надеяться на линейность: если пробное восстановление небольшой копии заняло десять минут, это не значит, что копия в двадцать раз больше восстановится за три часа двадцать минут.
Сводная смета: от первого чтения до первого запроса
Соберём условный пример целиком. База (кластер) 400 ГБ, измеренная полезная скорость между площадками 35 МБ/с, диск получателя читает порядка 200 МБ/с, поток изменений в среднем режиме 6 ГБ/час. Время для каждого этапа:
| Этап | Расчёт | Время |
|---|---|---|
| Подготовка копии (чтение, сжатие, упаковка конвейером) | Идёт параллельно с отправкой; закладываем запас на старт и сбои | около 20 минут |
| Передача по сети | 400 000 МБ / 35 МБ/с | около 3,2 часа |
| Проверка на получателе | 400 000 МБ / 200 МБ/с | около 33 минут |
| Накопленные изменения за ~4 часа и догон | 24 ГБ при запасе скорости ~33 МБ/с | около 12 минут |
| Запуск и проверка работоспособности базы | Определяется пробным восстановлением | например, 30 минут |
Складываем: 0,33 + 3,2 + 0,55 + 0,2 + 0,5 ≈ 4,8 часа. Это уже заметно больше «почти часа» из первого абзаца, хотя шестичасовое окно всё ещё вмещает результат. Теперь вспомним, что скорость на больших объёмах могла оказаться ниже. Если средняя упадёт до 25 МБ/с, передача растянется до 400 000 / 25 = 16 000 секунд, то есть около 4,4 часа, и итог приблизится к шести часам и выйдет за них, как только добавятся поправки на повторную передачу после обрыва. Если же при этом ночью включится пакетная обработка и журнал начнёт расти заметно быстрее, догон превратится из двенадцати минут в вопрос часа. Поэтому запас в расчёте нужен не из осторожности ради осторожности, а потому, что у каждого этапа свой разброс, и они накладываются друг на друга.
Итоговая формула, которую можно взять к себе и подставить свои измерения:
T = T_подготовки + V / v_полезная + V / v_чтения_получателя + (V_изменений / (v_полезная − v_WAL)) + T_запускаЗдесь V — объём кластера, v_полезная — устойчивая скорость, измеренная на вашем маршруте, v_WAL — скорость образования журнала в соответствующие часы, V_изменений — накопленный за время подготовки и передачи журнал. Для надёжности берите худшие из реальных замеров, а не средние, и пересчитывайте при изменении объёма: база растёт, а расчёт, сделанный по прошлогоднему размеру, устаревает так же, как прошлогодний прогноз погоды.
Правильный ответ на вопрос «за сколько база дойдёт до другой страны» поэтому звучит не как время последнего принятого байта, а как время до момента, когда на резервной площадке запущена база, догнавшая основную, проверенная и готовая отвечать на запросы. В нашем условном примере это около пяти часов, а не один, и именно эту цифру стоит сравнивать с окном обслуживания и с допустимым отставанием.