8 мин

Distributed SQL: когда выбирать Spanner, CockroachDB и YugabyteDB

Узнайте, когда распределённый SQL оправдывает затраты, чем отличаются Spanner, CockroachDB и YugabyteDB и как безопасно планировать мультирегиональные нагрузки.

Distributed SQL: когда выбирать Spanner, CockroachDB и YugabyteDB

Что означает distributed SQL

Distributed SQL - это архитектура реляционной базы данных, которая распределяет данные и обработку транзакций между несколькими машинами, но показывает приложениям одну логическую SQL-базу. В ней сохраняются таблицы, соединения, индексы, ограничения и ACID-транзакции, а также добавляются автоматическое разбиение данных, репликация и восстановление после сбоев.

Обычно систему относят к этой категории, если в ней есть такие свойства:

  • Реляционная схема и SQL-интерфейс запросов
  • Горизонтальное масштабирование между узлами базы данных
  • Транзакционная согласованность между разделами
  • Автоматическая репликация и переключение при сбоях
  • Согласованная работа как одной логической базы данных

Это определение важно, потому что база не становится distributed SQL, если просто добавить реплики для чтения к PostgreSQL или MySQL. Основной сервер с репликами всё равно направляет записи через один главный узел. Шардинг под управлением приложения распределяет записи, но заставляет приложение решать, где хранятся записи и как выполнять операции между шардами. Distributed SQL берёт большую часть этой ответственности на себя.

Место между обычной РСУБД и NoSQL

Distributed SQL объединяет реляционную модель программирования обычной РСУБД с масштабированием по горизонтали, характерным для распределённых хранилищ данных. Традиционные развёртывания PostgreSQL и MySQL хорошо работают, если основной экземпляр справляется с записью, а при сбое региона не требуется непрерывно принимать записи в другом месте. Реплики для чтения, кеширование, пулинг соединений и более удачные индексы могут развивать эту модель годами.

Многие базы NoSQL упростили распределение, ограничив соединения, транзакции или гарантии согласованности. Это по-прежнему разумно для нагрузок вроде больших потоков событий, временных кешей и записей, которые редко участвуют в транзакциях с несколькими строками. Реляционный кластер требует больше координации, поскольку приложения ожидают, что ограничения и транзакции останутся корректными после разделения данных между узлами.

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

Какие задачи он решает

Distributed SQL предназначен для приложений, чьи требования к доступности, географическому размещению или росту записи переросли архитектуру с одним основным сервером. Типичные примеры: глобальный SaaS-сервис, система бронирования без риска перепродажи и финансовый реестр, чьи инварианты должны сохраняться при сбоях узлов.

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

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

Как distributed SQL работает внутри

Distributed SQL делит данные на реплицируемые разделы и координирует изменения с помощью консенсуса и протоколов распределённых транзакций. База скрывает большую часть этой механики за SQL, но её поведение по-прежнему влияет на задержку, пропускную способность, схему и реакцию на инциденты.

Разделы определяют, где хранятся записи

Кластер делит логические таблицы на более мелкие единицы, которые могут независимо перемещаться между узлами. Spanner обычно называет их splits, CockroachDB - ranges, YugabyteDB - tablets. Каждая единица покрывает часть пространства ключей таблицы или индекса.

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

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

Репликация и консенсус защищают каждый раздел

У каждого раздела обычно несколько реплик, а группа консенсуса определяет принятую последовательность изменений. CockroachDB и YugabyteDB используют репликацию на базе Raft. Spanner использует репликацию на базе Paxos вместе со своей инфраструктурой времени.

Лидер или leaseholder координирует записи для группы реплик. Система фиксирует изменение на достаточном числе реплик, чтобы образовался кворум, и только затем считает его подтверждённым. Если узел исчезает, оставшиеся участники могут выбрать или назначить другого координатора, пока кворум доступен.

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

Распределённые транзакции координируют несколько разделов

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

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

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

Время и порядок требуют явных механизмов

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

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

Локальность определяет сетевой путь

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

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

Когда distributed SQL - правильный выбор

Distributed SQL подходит, когда географическая устойчивость, горизонтальная ёмкость записи или корректность между разделами достаточно важны, чтобы оправдать постоянные затраты на координацию. Крупной компании он нужен не автоматически, а небольшому продукту он может понадобиться, если бизнес-обещание требует строгой доступности в регионах.

Условия, при которых стоит оценивать решение

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

  • Сервис должен продолжать работу при сбое зоны или региона
  • Спрос на запись приближается к практическому пределу одной основной базы
  • Ручной шардинг потребует много времени от команды приложения
  • Транзакции должны оставаться корректными между узлами или локациями
  • Для записей нужно контролируемое географическое размещение

Эти условия нужно подтвердить цифрами. Определите требуемые RTO, RPO, задержку транзакций, пиковую скорость записи и домены отказа. Расплывчатого запроса на глобальное масштабирование недостаточно для выбора архитектуры.

Одного наличия пользователей в разных регионах недостаточно. Приложение с большим объёмом контента может разместить веб-серверы и кеши ближе к пользователям, сохранив базу в одном регионе. Реплики для чтения поддержат региональный просмотр, если допустимы слегка устаревшие результаты. Доводы становятся сильнее, когда пользователи из нескольких мест должны выполнять низколатентные записи по связанным данным.

Условия в пользу более простой базы

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

Жёсткие требования к задержке тоже могут склонять к одному региональному основному серверу. Локальная надёжная запись завершается гораздо быстрее, чем кворумная запись между удалёнными регионами. В системах с преобладанием аналитики операционные транзакции обычно следует отделять от длинных сканирований, а не ждать, что один кластер одинаково хорош для обоих типов работы.

Важны возможности команды. Управляемые сервисы уменьшают работу с оборудованием, исправлениями и управляющей плоскостью, но не отменяют конкуренцию в схеме, повторы транзакций, планирование запросов, управление ёмкостью и обработку инцидентов в приложении. Если у команды нет времени проверять поведение при сбоях, переход на распределённую базу может повысить риск.

Порог решения на основе альтернатив

Самое убедительное обоснование появляется, когда альтернатива уже сложна. Если инженеры готовы строить маршрутизацию арендаторов, карты шардов, правила транзакций между шардами, процедуры регионального повышения роли и отдельные инструменты миграций, базу с такими возможностями стоит внимательно оценить.

Если альтернатива - один управляемый экземпляр PostgreSQL с репликой для чтения и проверенными резервными копиями, для миграции нужны ясные доказательства. Сначала протестируйте текущую систему. Насыщение CPU может оказаться следствием неэффективного запроса, плохого управления соединениями, лишних индексов или отсутствующего кеша, а не потребности в горизонтальной записи.

Согласованность, доступность и задержка

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

CAP описывает поведение при сбоях

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

CAP не объясняет задержку при нормальной работе. Даже когда все соединения исправны, реплики должны обмениваться сообщениями. Более широкое инженерное решение включает поведение при разделении и объём координации, который приложение принимает при штатной работе.

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

Сильные чтения и намеренно устаревшие чтения различаются

Сильное чтение видит состояние базы, соответствующее запрошенной гарантии порядка. Некоторые продукты также предлагают чтения follower или с ограниченной устарелостью, где свежесть меняется на меньшую задержку и меньшую нагрузку на координатора записи.

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

Поведение read-your-writes нужно проверять с реальным драйвером и уровнем маршрутизации. После обновления следующий запрос может попасть на другой сервер приложения или другую конечную точку базы. Чтобы пользователь увидел принятое изменение, могут понадобиться токены сеанса, границы транзакции или настройка сильного чтения.

Изоляция определяет результаты параллельной работы

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

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

Повторы должны быть идемпотентными за пределами базы. Если код отправляет письмо или обращается к платёжному провайдеру до окончательной фиксации транзакции, повтор может продублировать побочный эффект. Запишите событие outbox в транзакции базы, зафиксируйте её, а внешнее действие поручите отдельному обработчику.

Расстояние задаёт нижнюю границу задержки записи

Межрегиональная транзакция не может завершиться быстрее, чем требуют сообщения её протокола. Время полного сетевого обмена 80 миллисекунд между участниками кворума добавляет реальное время ещё до выполнения запроса, обслуживания индексов, работы приложения и ожидания в очередях.

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

Измеряйте процентильную задержку, а не среднюю. Перемещение лидера, конкуренция, остановки хранилища и повторы проявляются в хвосте распределения. Схема, которая выполняет цель по медиане, но пропускает 99-й процентиль при обычной балансировке, всё равно может вызвать заметные сбои для пользователей.

Сравнение Spanner, CockroachDB и YugabyteDB

Spanner, CockroachDB и YugabyteDB решают похожие задачи распределения, но различаются моделью развёртывания, совместимостью, реализацией транзакций и операционными предпосылками. Выбирать между ними нужно, проверяя поведение приложения, а не только ориентируясь на общий ярлык SQL.

ОбластьGoogle SpannerCockroachDBYugabyteDB
Основной SQL-интерфейсGoogleSQL или диалект PostgreSQLSQL, совместимый с PostgreSQL, через wire protocol PostgreSQLYSQL для SQL, совместимого с PostgreSQL, а также YCQL для доступа в стиле Cassandra
Основа репликацииГруппы Paxos с упорядочиванием на основе TrueTimeРепликация Raft по rangesРепликация Raft по tablets
Типичная поставкаУправляемая база данных Google CloudУправляемый облачный сервис или самостоятельное развёртываниеУправляемый облачный сервис или самостоятельное развёртывание
Риск для переносимостиДиалект и поведение, зависящее от платформыПробелы в функциях, расширениях и семантике PostgreSQLРазличия версий и функций между YSQL и PostgreSQL
Естественный сценарий оценкиСистемы в Google Cloud, которым нужно глобальное размещение транзакцийКоманды, желающие разрабатывать в стиле PostgreSQL с распределённой работойКоманды, которым нужен доступ в стиле PostgreSQL или выбор между SQL и API в стиле Cassandra

Spanner подходит стратегии с управляемым Google Cloud

Spanner подходит организациям, готовым использовать управляемую базу Google Cloud и проектировать систему с учётом её диалекта, топологии и операционной модели. TrueTime поддерживает внешне согласованные транзакции, то есть зафиксированные транзакции соблюдают порядок реального времени в рамках документированной семантики.

Его диалект PostgreSQL может уменьшить различия в синтаксисе SQL, но диалект не означает полную эквивалентность PostgreSQL. Расширения, административные функции, системные каталоги, типы данных, драйверы и предположения ORM всё равно нужно проверять. Командам стоит составить список всех зависимостей от базы, прежде чем считать существующее приложение переносимым.

Spanner заслуживает особого внимания, если нужная система уже зависит от идентификации, сети, наблюдаемости и региональных настроек Google Cloud. Управляемая модель избавляет от администрирования узлов базы, но проектирование схемы, настройка запросов, квоты, управление стоимостью и восстановление приложения остаются обязанностью клиента.

CockroachDB подходит распределённым приложениям в стиле PostgreSQL

CockroachDB подходит командам, которым нужен доступ к приложению в стиле PostgreSQL при распределении транзакционных данных по ranges. По умолчанию он использует сериализуемую изоляцию, поэтому приложения должны корректно повторять транзакции, отклонённые из-за конкуренции или конфликтов упорядочивания.

Совместимость нужно проверять на уровнях миграций, драйверов и ORM. Расширения PostgreSQL и специализированное поведение могут отсутствовать или отличаться. Запросы, зависящие от планов выполнения на одном узле, также могут вести себя иначе после деления таблиц и индексов между ranges.

Перемещение ranges и автоматическая балансировка упрощают изменение ёмкости, но плохой выбор первичного ключа всё равно способен создать горячие ranges. Мультирегиональные абстракции помогают выразить локальность таблиц, однако разработчикам нужно решить, какие записи региональные, какие глобальные и где координировать записи.

YugabyteDB подходит для YSQL и смешанных API

YugabyteDB подходит приложениям, которым важен реляционный интерфейс, совместимый с PostgreSQL, и может быть полезен отдельный API, совместимый с Cassandra. YSQL предоставляет реляционные таблицы и распределённые транзакции, а YCQL использует другую модель данных и не должен восприниматься как ещё один путь ко всем операциям YSQL.

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

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

Полезный тест продукта опирается на данные приложения

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

Не сравнивайте только пиковое число транзакций в секунду. Записывайте задержки p50, p95 и p99, частоту конфликтов и повторов, объём данных между регионами, усиление хранения, время восстановления и усилия оператора при смоделированном инциденте. Лучший выбор соответствует целям по корректности и восстановлению при приемлемой стоимости и операционной нагрузке.

Глобальный SaaS с региональными пользователями

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

Глобальное SaaS-приложение выигрывает от distributed SQL, когда арендаторам нужно региональное размещение данных и транзакционный доступ без отдельных стеков баз данных для каждой географии. Такой дизайн лучше всего работает, когда аренда явно отражена в схеме, а большинство транзакций остаётся внутри одного арендатора.

Локальность арендатора должна следовать договорам и трафику

Идентификатор арендатора может определять размещение: европейские записи останутся в разрешённых европейских локациях, а записи другого клиента - в стране или регионе по договору. Это сохраняет одну логическую схему и допускает разные физические политики.

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

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

Для региональных чтений нужна явная политика свежести

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

Размещение записи должно следовать за обычным автором записи каждого арендатора. Если сотрудники клиента в основном работают в Сингапуре, координация его записей на другом континенте создаёт ненужную задержку. Процедура миграции арендатора должна обновлять размещение без потери записей, нарушения требований к резидентности и направления кешей приложения на старые локации.

Глобальный код приложения должен выдерживать перемещения

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

Мониторинг должен разделять пользовательскую задержку по регионам и классам арендаторов. Глобальная средняя величина может скрыть одну удалённую группу клиентов, которая платит за несколько лишних сетевых переходов. Идентификаторы трассировки, связывающие API-спаны с выражениями базы, упрощают поиск ошибок локальности.

Финансовые процессы и реестры

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

Реестр должен сохранять проверяемую последовательность проводок

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

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

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

Идемпотентность делает повторы безопасными

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

CREATE TABLE payment_attempts (
    account_id UUID NOT NULL,
    idempotency_key TEXT NOT NULL,
    provider_reference TEXT,
    status TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL,
    PRIMARY KEY (account_id, idempotency_key)
);

Если два обработчика отправляют одну операцию, уникальное ограничение определяет, чья вставка успешна. Проигравший обработчик должен прочитать существующую запись и вернуть её установленный результат. Он не должен создавать повторное списание у провайдера только потому, что транзакция базы была повторена.

Внешние вызовы требуют границы транзакции

База не может атомарно зафиксировать изменения вместе с независимым платёжным провайдером, если оба не участвуют в специализированном протоколе координации, чего у большинства публичных API нет. Оставляйте сетевой вызов вне транзакции базы и моделируйте процесс явными состояниями, например pending, authorized, captured, failed и reversed.

Транзакционный outbox может публиковать зафиксированные изменения для последующих обработчиков. Потребители должны устранять дубликаты по идентификатору события, поскольку доставка сообщения может произойти несколько раз. Это обеспечивает восстанавливаемую обработку без заявления о невозможной единой транзакции между всеми сервисами.

Горячим счетам нужен дизайн под конкретную нагрузку

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

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

Запасы, бронирование и резервирование

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

Условные записи предотвращают перепродажу

Условное обновление резервирует запас только при наличии нужного количества. Число затронутых строк сообщает приложению, успешно ли распределение.

UPDATE inventory
SET available = available - 1
WHERE sku = $1
  AND available > 0;

Это выражение должно быть в одной транзакции с записью о резервировании. Если сначала прочитать доступность, а затем уменьшить её, возникнет гонка, если уровень изоляции и обработка предиката не защищают решение. Ограничения базы должны дополнительно запрещать отрицательные количества.

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

Удержания отделяют распределение от платежа

Временное удержание резервирует запас, пока идёт оплата или подтверждение пользователем. Храните время его истечения и статус, затем превращайте его в подтверждённое бронирование условной транзакцией. Обработчик истечения должен освобождать только ещё активные удержания, поскольку подтверждение и истечение могут происходить одновременно.

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

Длительность удержания - решение о продукте и ёмкости. Десятиминутное удержание может быть разумным при оформлении заказа, но в период ажиотажа способно заблокировать заметную долю дефицитного запаса. Измерьте отказы и время завершения платежа до выбора срока.

Экстремальная конкуренция не масштабируется линейно

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

Региональные квоты уменьшают координацию, но меняют семантику. Если в Европе остались неиспользованные единицы, а другой регион всё распродал, системе нужен безопасный способ передать квоту или принять временный дисбаланс. Используйте этот шаблон, только если бизнес может определить порядок согласования региональной ёмкости.

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

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

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

SLO должны определять домены отказа

Цель доступности требует указать нагрузку и сценарий сбоя. Определите, должен ли сервис переживать отказ одного узла, одной зоны доступности или целого региона. Укажите допустимую частоту ошибок и задержку во время события, а не только после восстановления.

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

RTO определяет, как быстро должен вернуться сервис. RPO определяет, какой объём зафиксированных данных допустимо потерять. Синхронная кворумная репликация может поддерживать цель нулевой потери зафиксированных данных для охваченных сбоев, но лишь пока нужные реплики и путь приложения работают так, как задумано.

Переключение создаёт заметные события для приложения

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

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

Ёмкость после сбоя требует явного расчёта. Если три региона обычно работают примерно на 70 процентах загрузки, после потери одного не останется места для его доли работы. Резерв ёмкости стоит денег, но топология без ёмкости на переключение не выполняет заявленную цель.

Учения проверяют дизайн

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

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

Репликация не заменяет резервную копию

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

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

Резидентность данных и архитектура под требования соответствия

Distributed SQL может размещать арендаторов или группы записей в разрешённых регионах, но соответствие зависит от каждой копии, пути доступа и операционного процесса. Локальность базы - один контроль в более широкой программе.

Правила резидентности нуждаются в точных определениях

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

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

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

Политики размещения должны включать операции жизненного цикла

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

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

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

Для глобальной отчётности могут понадобиться производные наборы данных

Глобальная панель может конфликтовать со строгим размещением, если сканирует необработанные данные клиентов в разных регионах. Региональная обработка может локально вычислять разрешённые агрегаты, а затем публиковать нечувствительные результаты в центральном хранилище отчётности.

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

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

Планирование стоимости и производительности

Запустите базовое приложение
Создайте API и интерфейс в чате, а затем сосредоточьтесь на выборе базы данных, а не на шаблонном коде.

Distributed SQL стоит дороже базовой базы в одном регионе, потому что поддерживает резервную ёмкость и координирует работу по сети. Вложения всё же могут быть оправданы, если они заменяют дорогую работу по шардингу или предотвращают потери, превышающие операционную надбавку.

Вычисления и хранение включают накладные расходы репликации

Логический набор данных объёмом 2 ТБ с тремя полными репликами начинается примерно с 6 ТБ реплицированных данных ещё до вторичных индексов, временного пространства для уплотнения, резервных копий и метаданных. Фактическая тарификация и сжатие зависят от продукта, поэтому оценку стоит строить на измеренном физическом хранилище, а не только на логическом размере таблиц.

Вычислительные ресурсы должны покрывать штатную работу, обработку консенсуса, балансировку, резервное копирование и резерв на сбои. Узлы не взаимозаменяемы по пропускной способности, если один раздел горячий. Добавление ёмкости помогает, только когда нагрузка может по ней распределиться.

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

Сетевые расходы могут стать значимыми

Репликация отправляет записи между локациями реплик. Межрегиональные запросы, потоки изменений, резервные копии и трафик приложения добавляют передачу данных. Активный трафик в нескольких регионах может создать счёт, который тестирование в одном регионе никогда не покажет.

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

Ошибки локальности повышают и стоимость, и задержку. Сервис в одном регионе может постоянно обращаться к координатору в другом из-за выбора конечной точки или размещения арендатора. Распределённая трассировка и разбивка стоимости по регионам помогут выявить этот шаблон.

Пользовательские сценарии показывают накопленную задержку

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

Предположим, в одном сценарии есть две последовательные кворумные записи, каждая добавляет 90 миллисекунд сетевой координации. Это даёт около 180 миллисекунд ещё до обработки приложением. Объединение изменений с одним атомарным решением может убрать фиксацию, а распараллеливание независимых чтений может сократить путь.

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

Сравнивайте полную стоимость владения с реальными альтернативами

Нужно сравнивать distributed SQL не с воображаемой базой без операционных затрат, а с конкретной альтернативой: управляемым PostgreSQL, репликами, сервисами шардинга, региональным восстановлением, маршрутизацией приложения и инженерами, которые всё это поддерживают.

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

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

Шаблоны проектирования схемы и приложения

Схема distributed SQL хорошо работает, когда пути доступа распределяют независимую работу, сохраняя связанные транзакции рядом. Перенос одноузловой схемы без изменений может сохранить корректность, но привести к плохой задержке или серьёзной конкуренции.

Первичные ключи влияют на распределение

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

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

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

При конкуренции сначала меняйте дизайн, а затем ёмкость

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

Замените точные глобальные счётчики на секционированные, если допустима временная агрегация. Версионируйте конфигурацию вместо частого обновления одной строки. Для денежных состояний сохраняйте инвариант учёта и ищите параллелизм в проводках только на добавление или независимых подсчетах, а не ослабляйте корректность.

Длинные транзакции чтения, изменения и записи усиливают конфликты. Читайте минимально нужный набор, избегайте взаимодействия с пользователем внутри транзакции и быстро фиксируйте изменения. Если бизнес-работа занимает минуты, представьте её как автомат состояний из нескольких коротких транзакций.

Повторы должны быть частью контракта приложения

Драйверы могут повторять отдельные выражения или передавать приложению ошибку, допускающую повтор. Нужно понимать, какой уровень отвечает за повтор всей транзакции. Частичный повтор может использовать устаревшие решения или пропустить предыдущие чтения.

Цикл повторов должен иметь максимальное число попыток, случайную задержку и инструментирование. Записывайте тип конфликта, затронутую операцию, число попыток и итог. Неограниченные повторы превращают конкуренцию в скрытую задержку и могут перегрузить кластер.

Бизнес-запросам нужны стабильные идентификаторы, чтобы неопределённый ответ клиенту можно было безопасно проверить. Если база зафиксировала изменения, но ответ потерялся, клиент должен запросить уже установленную операцию, а не отправлять семантически новый запрос.

Изменения схемы требуют репетиции в масштабе рабочей среды

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

Используйте миграции expand-and-contract. Сначала добавьте совместимые поля или таблицы, затем разверните код, умеющий работать с обеими формами, выполните заполнение контролируемыми пакетами, переключите чтения и удалите старую форму после проверки. План отката должен учитывать данные, записанные новой версией.

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

Чек-лист внедрения и proof of concept

Полезный proof of concept проверяет одну репрезентативную нагрузку по явным целям корректности, задержки, устойчивости и стоимости. Общие бенчмарки не могут определить, хорошо ли поведут себя конкретная схема и приложение.

Выберите нагрузку с реальными ограничениями

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

Определите успех до запуска теста:

  • Корректные результаты при конкуренции и повторах
  • Задержка p50, p95 и p99 по регионам
  • Устойчивая пиковая пропускная способность с резервом на сбой
  • Поведение восстановления при сбоях узла и региона
  • Измеренная стоимость вычислений, хранения и сети

Запас надёжности должен следовать из ожидаемого роста и ёмкости на сбой, а не из произвольного множителя. Если потеря одного региона входит в область требований, оставшиеся локации должны обработать перенаправленную нагрузку во время теста.

Создайте реалистичную поверхность приложения

API и небольшой пользовательский интерфейс показывают последовательность транзакций, поведение драйвера и воспринимаемую пользователем задержку, которые может пропустить инструмент только для базы. Koder.ai может через чат создать интерфейс React, backend на Go и базовую версию на PostgreSQL. Его режим планирования помогает определить процесс до генерации, а экспорт исходного кода позволяет инженерам адаптировать слой данных для выбранной базы.

Используйте сгенерированное приложение как основу для тестов, а не как доказательство совместимости базы. Запустите миграции, проверьте сгенерированный SQL, настройте официальный драйвер и осознанно реализуйте повторы транзакций. Снимки и откат Koder.ai защищают итерации приложения, но не заменяют резервные копии базы или проверки восстановления.

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

Проверьте штатную работу и сбои

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

Собирайте сведения об отменах транзакций, попытках повторов, ответах о недоступности, смене лидера, глубине очередей, использовании диска и региональной передаче. Запишите, что пришлось делать оператору. Автоматическое восстановление, требующее недокументированного ручного шага, ещё не готово к рабочей среде.

Восстановите резервную копию в отдельную среду и проверьте инварианты приложения. Для запасов убедитесь, что распределение не превышает запас. Для реестра пересчитайте балансы и проверьте сбалансированность проводок. Для SaaS с арендаторами убедитесь, что после восстановления сохранились политики размещения и доступа.

Проверьте совместимость до миграции

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

Запустите репрезентативные миграции на полноразмерной копии или сгенерированном наборе данных. Измерьте длительность заполнения, задержку change-data-capture, стоимость параллельной работы и время переключения. Если миграция использует двойную запись, определите способ обнаружения расхождений и авторитетную систему на каждом этапе.

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

Проверьте готовность к рабочей среде

При проверке перед запуском нужно назначить владельцев эксплуатации базы, повторов в приложении, безопасности, политики резидентности, стоимости и реакции на инциденты. В неё должны входить панели, оповещения, инструкции, пороги ёмкости, доказательства восстановления и точка решения об откате.

Итоговым решением всё ещё может быть сохранение PostgreSQL или MySQL. Proof of concept успешен, когда даёт надёжные доказательства, даже если они показывают, что распределённый вариант стоит больше, чем оправдывают текущие требования. Когда требования поддерживают внедрение, мигрируйте постепенно, измеряйте каждый этап и сохраняйте проверенный путь назад, пока новая система не докажет себя под реальной нагрузкой.

FAQ

Что такое база данных «distributed SQL» простыми словами?

Распределённая SQL-база данных даёт привычный реляционный интерфейс и SQL, то есть таблицы, соединения, ограничения и транзакции, но работает как кластер на нескольких машинах, часто в разных регионах, оставаясь одной логической базой данных.

На практике она объединяет:

  • привычные SQL и ACID-гарантии
  • горизонтальное масштабирование за счёт добавления узлов
  • высокую доступность и устойчивость к сбоям без ручного шардинга
Чем distributed SQL отличается от обычной схемы PostgreSQL или MySQL?

Одноузловая реляционная БД или схема с основным сервером и репликами обычно проще, дешевле и быстрее для OLTP в одном регионе.

Распределённый SQL становится оправданным, когда иначе понадобятся:

  • шардирование силами приложения
  • сложное переключение между регионами при сбоях
  • строгая согласованность между зонами или регионами
  • требования к размещению данных при единой операционной модели
Зачем системам distributed SQL нужны протоколы консенсуса вроде Raft или Paxos?

Большинство систем опирается на две ключевые идеи:

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

Именно это помогает сохранять строгую согласованность при сбоях узлов, но добавляет сетевые накладные расходы.

Как данные делятся и размещаются между узлами и регионами?

Они делят таблицы на небольшие части, часто называемые разделами или шардами, либо используют названия поставщика, например ranges, tablets или splits. Каждый раздел:

  • имеет собственную группу реплик
  • может размещаться на определённых узлах и в регионах
  • может перемещаться при балансировке кластера

Обычно на размещение влияют политики, чтобы «горячие» данные и основные источники записи находились рядом, сокращая сетевые задержки.

Почему транзакции в distributed SQL могут быть медленнее, особенно между регионами?

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

  • блокировки или проверка изменений у участников
  • подтверждения репликации от кворума
  • согласованное решение о фиксации

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

Какие признаки яснее всего показывают, что мне действительно нужен distributed SQL?

Рассмотрите distributed SQL, если верны хотя бы два пункта:

  • у вас много пользователей в нескольких регионах и нужны согласованные данные
  • требуется автоматическое переключение между зонами или регионами при строгих RTO/RPO
  • вертикального масштабирования уже не хватает для записей
  • для ключевых транзакций нужны строгие гарантии, например для денег, запасов или бронирований
  • требования соответствия обязывают размещать данные географически

Если нагрузка умещается в одном регионе с репликами и кешированием, обычная реляционная БД часто остаётся лучшим выбором.

Что даёт строгая согласованность и какой ценой?

Строгая согласованность означает, что после фиксации транзакции чтения не увидят более старые данные.

Для продукта это помогает предотвратить:

  • двойное списание и неверные балансы
  • продажу последней единицы товара нескольким покупателям
  • бронирование одного места двумя пользователями

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

Как безопасно обрабатывать повторы с distributed SQL и идемпотентностью?

Опирайтесь на ограничения базы данных и транзакции:

  • храните idempotency_key или похожий ключ для каждого запроса или попытки
  • добавьте уникальное ограничение, например (account_id, idempotency_key)
  • в одной транзакции записывайте бизнес-сущность и связанные строки реестра или outbox

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

Как выбрать между Spanner, CockroachDB и YugabyteDB?

Практичное разделение такое:

  • Spanner: обычно управляемая служба в GCP, сильная поддержка мульти-региональной архитектуры, а выбор диалекта SQL влияет на переносимость.
  • CockroachDB: интерфейс и wire protocol в стиле PostgreSQL, управляемое или самостоятельное развёртывание, но совместимость с PostgreSQL не стопроцентная.
  • YugabyteDB: SQL API, совместимый с PostgreSQL, YSQL, а также опциональный API в стиле Cassandra, YCQL, управляемое или самостоятельное развёртывание.

Перед выбором проверьте реальный ORM, миграции и используемые расширения PostgreSQL. Не рассчитывайте на полную замену без доработок.

Какой план PoC подойдёт перед переходом на distributed SQL?

Начните с узкого PoC вокруг одного критичного сценария, например оформления заказа, бронирования или проводки в реестре. Проверьте:

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

Если нужна помощь с оценкой стоимости и тарифов, посмотрите страницу тарифов. Связанные заметки по реализации есть в блоге.

Похожие статьи