Регионы¶
Provisa даёт вам два примитива для размещения данных: регион и закрепление за регионом, то есть создание региона и назначение ему таблицы. Ни один из них сам по себе не является политикой. То, для чего вы их используете, делится на три группы:
- Производительность. Задержка до читателей, свежесть их копии и пригодность движка: где находится его центр обработки данных, какое хранилище он читает, сколько у него процессора и памяти.
- Стоимость. Где выполняется работа и на чём: собственное оборудование или облако, большой движок или маленький, и во что обходится перемещение данных между местами (egress).
- Суверенитет. Кто контролирует данные и куда они могут попадать: требования закона о размещении (где персональные данные можно обрабатывать и где хранить) и собственные линии контроля организации, например подразделение или дочерняя компания, которая держит свои данные и инфраструктуру под собственным контролем.
Механика для всех трёх одна и та же. Различаются только правила, которые вы пишете поверх.
Регион — это движок и его хранилища в одном месте¶
Регион — это место, где Provisa выполняет работу и хранит то, что после неё остаётся. У каждого региона свой движок и свои хранилища.
| Хранилище | Что в нём |
|---|---|
engine |
Движок федерации, выполняющий инструкции в этом регионе |
replicas |
Реплики таблиц, закреплённых здесь, и таблиц без региона, которые копирует этот регион |
views |
Копии материализованных представлений этого региона |
cache |
Закешированные ответы |
state |
Состояние сборок и обновлений |
record |
Запись каждого обслуженного здесь запроса |
Все регионы регулирует одна модель. Источники, таблицы, связи, роли, правила строк и колонок, представления и настройки свежести объявляются один раз, в одном хранилище модели, и каждый регион обслуживает эту же модель, поэтому определения не могут разойтись между регионами. Изменение доходит до каждого региона с одной и той же меткой, после чего каждый регион к нему сходится.
Платформа объявляет физические регионы, в которых работают её узлы, с адресом, по которому отвечает каждый регион. Модель каждой организации выбирает, какие из этих регионов она использует, и называет своё хранилище для каждой роли в каждом регионе. Узел запускается в регионе командой provisa run --region <id> и обслуживает этот регион для каждой организации, которая его выбрала. Когда регионы объявлены, узел, запущенный без --region, отказывается запускаться и перечисляет регионы, которые мог бы обслуживать.
platform:
regions:
- { id: eu, address: "https://eu.provisa.example" }
- { id: us, address: "https://us.provisa.example" }
stores:
- { id: eu_engine, url: "${secret:eu-trino-url}", kind: trino }
- { id: us_engine, url: "${secret:us-trino-url}", kind: trino }
- { id: eu_data, url: "${secret:eu-pg-url}" }
- { id: us_data, url: "${secret:us-pg-url}" }
- { id: eu_cache, url: "${secret:eu-redis-url}" }
- { id: us_cache, url: "${secret:us-redis-url}" }
regions:
- { id: eu, engine: eu_engine, replicas: eu_data, views: eu_data, cache: eu_cache, state: eu_data, record: eu_data }
- { id: us, engine: us_engine, replicas: us_data, views: us_data, cache: us_cache, state: us_data, record: us_data }
При загрузке конфигурация отклоняется с указанием причины, если регионы не согласуются. Регион должен назвать объявленное хранилище для каждой роли. Его replicas и views должны быть одним хранилищем, а хранилище движка должно называть kind движка. Если у платформы больше одного региона, встроенный файл движка отклоняется, потому что другие регионы не могут до него добраться.
Несколько регионов могут делить один экземпляр базы данных, один Redis или один бакет объектного хранилища. Всё, что хранит регион, несёт регион в своём имени, поэтому их хранилища не конфликтуют.
Развёртывание, которое не объявляет регионов, имеет один неявный регион и нигде не показывает регион. Нет поля региона и флага --region, а конфигурация, называющая регион, отклоняется.
Закрепление за регионом: таблица называет свой домашний регион¶
Таблица может назвать один из регионов своей организации своим домашним регионом. Только он строит и обновляет её реплику и только он может держать её горячей. Все остальные регионы читают таблицу из реплики домашнего региона, на месте, по адресу, который даёт модель. Правила строк и колонок читателя входят в эту инструкцию, поэтому фильтрация происходит в домашнем регионе и границу пересекает только то, что читателю разрешено видеть.
Некоторые следствия:
- Ни один другой регион не читает источник таблицы; они читают только реплику домашнего региона. Источник, который вы реплицируете, чтобы защитить его от нагрузки, остаётся защищённым.
- Если реплика не построена или домашний регион недоступен, запрос отклоняется с указанием домашнего региона. Источник вместо этого не читается напрямую.
- Закреплённую таблицу, которая не реплицируется, с
replicateNever или с настройкой, ещё не потребовавшей копии, каждый регион читает напрямую из её источника, как любую нереплицируемую таблицу. - Счётчик горячести таблицы — это трафик только её домашнего региона.
- Материализованное представление тоже может назвать регион. Тогда оно строится только там, а все остальные регионы читают эту копию, точно так же, как для закреплённой таблицы.
Региону, который читает реплику другого региона, нужен движок, способный её прочитать: duckdb, motherduck, pg, trino или trino-byo. Хранилище replicas домашнего региона должно быть сервером PostgreSQL. Конфигурация называет и то, и другое, когда они не подходят.
Источник тоже может назвать регион, но этот регион лишь заполняет форму, когда вы регистрируете новую таблицу источника. Он ничего не решает о том, где находятся данные, и его последующее изменение не перемещает ни одной таблицы.
Таблицы без региона копируются там, где их читают¶
Таблицу, не называющую регион, можно копировать в каждый регион. Когда её настройка replicate требует копии, регион, к которому подключился читатель, строит её в своём хранилище. Материализованное представление, не называющее регион, строится в каждом регионе, каждая копия в хранилище представлений этого региона.
Поэтому новый регион означает больше копий и больше работы по обновлению. Больше регулирования он не означает никогда. Одна модель регулирует каждую копию, и в каждом регионе действуют одни и те же правила строк и колонок. Сборка представления в регионе регулируется как администратор организации, действующий в этом регионе, поэтому копия каждого региона содержит то, что там можно хранить.
Три причины использовать регионы¶
Производительность¶
Регионы, используемые только ради производительности, не объявляют межрегиональных правил. Таблицы, роли и правила те же, что вы написали бы для одного региона, а закрепление решает, где выполняется работа:
- Задержка. Читатели подключаются к ближайшему региону, и его движок, кеш и копии для них локальны.
- Свежесть. Таблица, закреплённая там, где она меняется, обновляется там, рядом со своим источником.
- Пригодность движка. В каждом регионе работает свой движок, поэтому движок можно подобрать к месту: к центру обработки данных, где он находится, к хранилищу, которое он читает, к его процессору и памяти.
Пример: два одинаковых региона. Объявите east и west в двух центрах обработки данных, каждый с одним и тем же видом движка и одними и теми же видами хранилищ, и не закрепляйте ни одной таблицы. Каждый регион обслуживает ближайших к нему читателей: строит свои копии того, что они читают, и кеширует их ответы. Оба могут стоять за одним балансировщиком нагрузки и делить нагрузку. Расписание обновления одно — расписание модели, — и оба региона начинают обновлять свои копии по нему, но их движки могут закончить не за одно и то же время. Поэтому в каждый момент не гарантировано, что оба находятся в одном состоянии, и читатель, переведённый из одного региона в другой, может увидеть данные другой свежести. Provisa не переводит клиента в другой регион, когда один останавливается; куда направить клиента, решает балансировщик нагрузки.
Стоимость¶
Регионы ради стоимости тоже не объявляют межрегиональных правил. Они размещают работу там, где её дешевле выполнять:
- Собственное оборудование и облако. Держите регион на собственной площадке, на оборудовании, которым вы уже владеете, для таблиц и читателей, которые там, а другой регион запускайте в облаке для остального.
- Размер движка. Запустите большой движок в одном регионе для эпизодической тяжёлой работы, а маленький в другом — для повседневного чтения. Читатели выбирают регион по его адресу.
- Egress. Читатели в других регионах получают только отфильтрованные строки из реплики закреплённой таблицы, а большая таблица, закреплённая за одним регионом, не копируется в каждый регион.
Суверенитет¶
Регионы ради суверенитета объявляют межрегиональные правила, будь причина в законе или в организации: дочерняя компания, закрепляющая свои таблицы за собственным регионом, обрабатывает и хранит их на своей инфраструктуре и через эти правила решает, что читает остальная группа. Это обычные правила строк и колонок, написанные на атрибутах, которые говорят, где находится читатель или узел, выполняющий работу:
current_setting('provisa.region')— это регион узла, отвечающего на запрос, когда платформа объявляет регионы. Фильтр строк, написанный на нём, удерживает строки региона в этом регионе.- Атрибут
regionучастника даёт ему производные ролиregionиregion__<value>, поэтому запись маски или предоставления может назватьanalyst+region__eu. Собственная фоновая работа узла несёт его регион так же. См. Роли: предоставленные, производные и мета.
Вместе с закреплением эти правила решают, что пересекает границу. Персональные данные закреплённой таблицы хранятся и обрабатываются в её домашнем регионе, а читатель в другом месте получает только то, что разрешают его правила, отфильтрованное дома. Представление без региона, построенное в каждом регионе, содержит то, что может видеть администратор этого региона, поэтому копия в одном регионе может включать строки, которые копия в другом регионе пропускает.
Кто может закрепить таблицу¶
Установка, изменение или удаление региона таблицы, источника или материализованного представления перемещает данные через границу. Для этого нужно право data_residency в дополнение к владению объектом через его домен. Предоставление называет значения, которые оно покрывает: регионы организации и «без региона». Перемещение объекта между двумя регионами требует предоставления, покрывающего оба. Сохранение за пределами предоставления отклоняется с указанием непокрытого значения.
Право существует только тогда, когда платформа объявляет регионы. Кто может изменять всё остальное в объекте, по-прежнему решает владение доменом. Регион не даёт собственных прав; организация, которая хочет, чтобы таблицами региона управляли люди этого региона, даёт им собственные домены.
Таблицу или представление можно также перевести в черновик. Черновик выведен из обслуживания и не предлагается ни одному читателю. Таблица, зарегистрированная через администрирование, начинает как черновик. Ответственный может просматривать её только на узлах региона, который она называет, а если она не называет никакого, то там, где находится он сам. Копия, которую загружает этот предпросмотр, остаётся в этом регионе до выпуска таблицы. Любая копия, которую другой регион держит с тех пор, когда регион таблицы ещё не был задан или был другим, выводится из обращения и удаляется, как у опубликованной таблицы. Черновик также даёт переносу между регионами чистый промежуток, когда таблица нигде не обслуживается: сторона первого региона переводит её в черновик, а владелец второго региона забирает её, задав свой регион.
См. также демо с двумя регионами.