Cloudflare вдвое сократила задержку DNS-сборки и память на 85%

Cloudflare рассказала в инженерном блоге, как ускорила доставку изменений DNS до серверов на границе сети. Автор поста вспоминает, что в 2022 году Zone Builder получал около 250 изменений DNS-записей в секунду, а сегодня около 700 (почти втрое больше) плюс около 100 других событий, например смен настроек зоны. Но дело не в числе событий: проблема в том, какая работа нужна для части из них и как она растёт с размером зоны. В некоторых зонах теперь больше 20 миллионов записей, и Cloudflare ждёт роста до сотен миллионов.
Путь изменения такой: клиент меняет запись через API или панель (или другой сервис Cloudflare меняет настройку зоны), изменение попадает в базу, возникает событие Kafka, DNS Kafka Aggregator собирает события из нескольких топиков и передаёт их Zone Builder. Тот читает нужные данные, превращает их в ключи для авторитетных DNS-серверов, сравнивает с Quicksilver (распределённым хранилищем «ключ-значение») и записывает только изменившееся. Эту работу Cloudflare называет сборкой (build).
В 2022 году уже сделали сборки по отдельным записям: в среднем они были в 150 раз быстрее полных, а на тестовой зоне с миллионом записей, в 4 250 раз. Следующим шагом стали настройки зоны. Полная сборка читает, кодирует и сравнивает каждую запись и держит в памяти всю зону; для крупнейших зон с десятками миллионов записей она просто не помещается. Сложность в том, что событие настройки зоны может прийти от многих продуктов, не всегда говорит, почему зона изменилась, и может затрагивать данные, общие для нескольких зон с одним именем. Слишком большая сборка тратит ресурсы, слишком маленькая рискует оставить на границе устаревшие или неверные DNS-данные.
Решение из двух частей. Первая, планировщик целевых сборок, который выбирает наименьшую сборку, безопасность которой можно доказать. Вторая, новый диспетчер, объединяющий работу по одной зоне. Вместе они сократили пиковую память на 85%; освободившийся запас позволил безопасно уменьшить паузы, которые конвейеру всегда были нужны для надёжности, и время от изменения DNS до записи данных в Quicksilver упало вдвое. Смена настроек больше не пересобирает зоны с десятками миллионов записей.
Чтобы планировщик мог решать, события научили сообщать, что именно изменилось: производитель событий теперь добавляет изменённые поля и настройки с прежними и новыми значениями, когда они известны. Планировщик выбирает один из пяти типов сборки: только ресурсы (записи по конкретным именам; обычные изменения A, AAAA, TXT, CNAME); ресурсы и метаданные (изменения NS и wildcard-записей); корень зоны и метаданные (например, Universal SSL, который может менять CAA-записи в корне домена); удаление (purge) зоны, которую больше не нужно публиковать; полная сборка зоны. Главное правило: каждый ключ, записанный целевой сборкой, должен побайтово совпадать с тем, что записала бы полная сборка; если этого не доказать, делается полная сборка. Обновление, которое лишь меняет метку времени, пока тоже вызывает полную сборку, пока не выяснено, кто и зачем его делает: планировщик никогда не превращает неопределённость в меньшую работу.
Есть одно намеренное исключение. Выше фиксированного порога по числу записей Zone Builder никогда не переходит к полной сборке: он пересобирает корень зоны, метаданные и все имена, названные в событиях очереди. Полная сборка таких зон не может завершиться, а пока она повторяется, она задерживает остальные изменения в своей партиции Kafka. Многие случаи, где иначе понадобилась бы полная сборка, связаны с несколькими зонами под одним именем, а блокировки зон (zone holds) снижают этот риск, не давая добавить то же имя в другой аккаунт. Для оставшихся редких случаев, например включения зоны в другой сети, отдельные имена можно пересобрать вручную.
Отдельно разобрано общее для нескольких зон: Quicksilver хранит ключи записей по каждой зоне, но один общий ключ метаданных на доменное имя, он работает как каталог внутренних идентификаторов зон, которыми можно отвечать на запросы. Во время подключения и отключения клиентов для одного домена ненадолго могут существовать несколько объектов зон, и по политике приоритета для публикации выбирается небольшой ограниченный набор. Изменение TXT-записи в одной зоне трогает только её ключи записей, а изменения NS и wildcard требуют обновить и записи, и общий ключ; его Zone Builder пересобирает целиком по свежему списку, а не правит старую копию, и записи зоны пишет раньше метаданных, которые на них ссылаются.
Планирование идёт дважды: событие даёт консервативный список работ, а непосредственно перед выполнением Zone Builder читает свежий срез публикации (настройки зоны, нужно ли публиковать её в данной сети и какие идентификаторы зон входят в общий ключ). Из-за этого целевая сборка может стать полной, сборка, удалением, сборка может быть пропущена, а ключ метаданных, перестроен по текущему набору кандидатов. Чтение идёт с реплик базы, чтобы не мешать записи клиентов. Поскольку Kafka и репликация базы работают независимо, DNS Kafka Aggregator задерживает события на время обычного отставания реплики, а финальная проверка в базе отклоняет чтение, если реплика всё ещё отстаёт.
Наконец, раньше записи и полные сборки обслуживали разные диспетчеры, и каждый мог объединять только свою работу. Их заменили единым: планировщик решает, что собрать, диспетчер, когда запускать. Если до старта сборки по зоне пришло несколько событий, их работа объединяется: например, изменение A-записи на www.example.com и wildcard на *.example.com превращаются в одну сборку двух имён и метаданных. Объединение только добавляет работу: если любому событию нужна вся зона, общая сборка становится полной, а удаление перекрывает любую пересборку. Описание диспетчера в доступной части текста обрывается на середине.
Ключевые факты
- Планировщик целевых сборок и единый диспетчер в Zone Builder вместе сократили пиковую память на 85% и вдвое уменьшили время от изменения DNS до записи данных в Quicksilver.
- Нагрузка выросла: с около 250 изменений записей в секунду в 2022 году до около 700 сейчас, плюс около 100 других событий; в крупнейших зонах больше 20 миллионов записей.
- Планировщик выбирает из пяти типов сборки; правило: ключи целевой сборки обязаны побайтово совпадать с ключами полной, иначе делается полная сборка.
- Для крупнейших зон выше фиксированного порога полная сборка не запускается вообще, пересобираются корень зоны, метаданные и имена из событий; редкие остальные случаи чинят вручную.
- Перед выполнением сборка проверяется по свежему срезу данных с реплик базы, а единый диспетчер объединяет события по одной зоне: объединение только добавляет работу.
Почему это важно
DNS, основа доступности любого сайта, и скорость, с которой изменение клиента доходит до серверов на границе сети, напрямую влияет на опыт пользователей. Cloudflare показывает, как инфраструктура на масштабе упирается не в число событий, а в то, что стоимость обработки растёт с размером зоны: при 20 миллионах записей и ожидаемом росте до сотен миллионов полная пересборка перестаёт помещаться в память. Результат по заявлению компании: пиковая память ниже на 85%, а время от изменения до записи в Quicksilver, вдвое меньше.
Кому это важно
Инженерам, которые строят конвейеры распространения конфигурации и данных, системы на Kafka и распределённые хранилища «ключ-значение». Полезно тем, кто решает, когда безопасно пересобирать только изменившуюся часть состояния, а когда нужна полная пересборка. Интересно и тем, кто пользуется DNS Cloudflare с очень большими зонами, хотя про реакцию клиентов в тексте ничего не сказано.
Как это применить
Из поста можно взять несколько приёмов. Делайте события описательными: пусть они несут, что именно изменилось и с какого значения на какое. Вводите явное правило корректности для частичных пересборок (результат побайтово совпадает с полной) и откатывайтесь к полной пересборке, когда доказать это нельзя: неопределённость не должна превращаться в меньшую работу. Планируйте дважды: консервативно по событию и заново по свежему срезу перед выполнением. Объединяйте работу по одной сущности так, чтобы слияние только добавляло объём. Для самых больших объектов заранее продумайте путь без полной пересборки и ручной запасной вариант.
Можно ли доверять
Это инженерный пост самой Cloudflare о собственной системе, то есть первоисточник, но цифры самоотчётные и независимо не проверены. Числа 85% и «вдвое» даны без абсолютных значений: в доступном тексте нет времени задержки в секундах до и после, не сказано, на каких зонах измерена память, и не названо время сокращённых пауз. Доступная часть материала обрывается внутри раздела о диспетчере, поэтому остальное (в том числе обсуждение безопасности сообщений Kafka) здесь не пересказано.
Риски и подводные камни
Целевые сборки опасны тем, что слишком маленькая сборка может оставить на границе устаревшие или неверные DNS-данные; поэтому Cloudflare вводит правило побайтового совпадения и свежую проверку перед выполнением. Остаются компромиссы: обновления, меняющие только метку времени, пока вызывают полную сборку, пока не выяснен их источник. Для крупнейших зон выше порога полная сборка отключена намеренно, а редкие случаи, например включение зоны в другой сети, чинят ручной пересборкой отдельных имён; сам порог в тексте не назван. Наконец, данные для одного имени может держать несколько зон, а общий ключ метаданных у них один; его пересобирают целиком по свежему списку, а не правят старую копию.
«Планировщик никогда не превращает неопределённость в меньший объём работы.»
— из блога Cloudflare о сборке DNS-данных