Pull to refresh
17
5
Subscribers
Send message

Что явилось критерием выбора ПГ и отказа от ydb?

Неправильный вопрос. Postgres уже был, никто от YDB не отказывался. Скорее команда отдала предпочтение и дальше использовать pg. Да, появляется некоторое прокси посередине, но оно работает по протоколу PostgreSQL.

SPQR тут помог только из 1 кластера PG сделать 8 таких кластеров.

почему в нагруженном проекте в Яндексе до сих пор выбирают для своих нагруженных проектов PostgreSQL, а не YDB?

Мой нелюбимый вопрос: почему X, а не Y? 🙂

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

Но есть один существенный недостаток: отсутствуют хорошие, готовые к использованию (или, скажем так, «дефолтные») решения для горизонтального масштабирования. Не так просто взять и запустить PostgreSQL на нескольких компьютерах так, чтобы они работали как единый кластер.

Существует два основных подхода к решению этой задачи:

  • Compute-Storage Separation (подходы Aurora и Neon);

  • шардирование (Citus, PgDog, Multigress, SPQR).

YDB популярна в Яндексе, я знаю много проектов где без YDB не обойтись.

с одной строны - трафик 5-10к rps (условные попугаи) и глубина хранения десятки лет с необходимостью быстрого доступа к древним данным, текущие ограничения по доступному железу - с другой стороны.

Вот именно для таких сценариев мы и проектировали SPQR. Шарды могут быть разными по ресурсам и работать на разных версиях PG. Создаешь шард(ы) на старом железе, скромными ресурсами и охлаждаешь средствами SPQR данные на этот/эти шарды.

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

есть примеры когда может не хватать? Я бы мог раскрыть как мы это решаем

Ну да, но всегда можно что-то придумать. Например, шардироваться по хэшу

Хороший пример. По сути, один и тот же набор данных обслуживает разные бизнес-роли с разными паттернами доступа.

Если шардироваться по заказам, SPQR действительно может сходить на все шарды и собрать ответы. Но результат будет:

  • нестрого консистентным,

  • и без глобальной сортировки. SPQR пока не делает distributed merge sort.

Так что тут у нас ещё не всё готово. Спасибо что подсветили.

Далее мысли вслух. Как это можно было быулучшить:

  1. Хранить вторичный индекс, который позволит заранее определить, на какие шарды идти, а какие можно пропустить. Тогда не будет fan-out по всему кластеру. Правда, пока непонятно как это могло бы выглядеть/работать в рамках SPQR.

  2. Строгой консистентности всё равно не будет. Для глобально отсортированной ленты можно сделать отдельное представление? Очередь?

Возможно ли использовать ваш роутер для шардирования по времени (данные телеметрии)?

Да, можно. Для этого не хватает только https://github.com/pg-sharding/spqr/issues/1657, а в остальном все готово. Можете отписаться в issue, а мы постараемся сделать ASAP.

И сможет ли он получить данные с нескольких шардов? Например, в данном случае, получить данные с определенным фильтром с 15 января по 15 февраля.

Да, роутер отправит этот запрос на каждый шард, а результат склеит.

Очень часто этого шага уже хватает

Проблема в том что очень часто на шаге #1 можно остановится 

Если можно не шардироваться, то нужно не шардироваться. Здравый смысл никто не отменял. Единственное, не согласен с утверждением "часто".

Отсюда растут Azure SQL, Greenplum, Citus, MySQL Proxy ну и все

Не путайте Greenplum и SPQR/Citus. И то, и другое это много постгресов. Но Greenplum можно использовать только для OLAP, а SPQR в первую очередь для OLTP. Citus про себя говорят HTAP, но кмк и мы туда со временем придем.

Все понятно

Я надеюсь что и правда все понятно, потому что из текста не могу считать сарказм это или нет :) Лучше уточнить

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

Вы сейчас описываете аналитический сценарий. Мы помним и держим в голове такое, рано или поздно SPQR придет в HTAP. Некоторые наши клиенты с помощью DataTransfer собирают данные для аналитики на отдельном postgresql и там выполняет такие запросы.

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

Первое что приходит в голову -- в слове SPQR 4 буквы, а в слове Citus 5 букв.

Второе что приходит в голову -- разработчики Citus они там, далеко. А разработчики SPQR тут, близко :)

И то, и то про шардирование, сделано архитектурно по-разному, результат примерно одинаковый. Если у вас есть чуть точнее вопрос, я смогу чуть точнее ответить :)

1) Проблема: была система с одним кластером PostgreSQL, как из нее сделать 4, 8, 16 и далее кластеров PostgreSQL? Шаг 1: начни ходить не непрямую в Postgres, а через прокси. Шаг 2: развези данные с одного шарда на другие с помощью REDISTRIBUTE KEY RANGE команды. Перевоз без даунтайма, приложение и пользователи этого перевоза никак не заметят. Если потом понадобится еще шардов добавить -- можно легко добавить и снова перенести данные.

2) Вам нужны Справочные таблицы.

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

Ситуация 1. Мы это называем виртуальные запросы. Запросы, которые может выполнить роутер, не передавая их на Postgres. Примеры:

SELECT true;
SELECT pg_is_in_recovery();
SELECT now()
-- и многие другие, надеюсь идея понятна

Ситуация 2. Ключ шардирования передали ранее в транзакции. Пример.

BEGIN; -- начинаем транзакцию
SET application_name="smth"; -- в начале может идти какой-то набор запросов, которые мы сохраняем в памяти роутера, в них нет ключа шардирования
SELECT * FROM users WHERE id=123; -- запрос, в котором есть ключ шардиования. С этого момента запрос выполняется на каком-то конкретном шарде/наборе шардов
SELECT * FROM taxes; -- а дальше уже не важно есть ли в запросах ключ шардирования, роутер передаст это на шард как есть
COMMIT;

Ситуация 3. Запрос к референсной таблице. Реф таблица -- это таблица, копия которой есть на каждом шарде. Пример:

SELECT * from taxes; -- роутер знает эту таблицу, знает что она референсная, отправляет на случайный шард

Ситуация 4. Не всегда в запросе/таблице может быть ключ шардирования, но иногда бывает что приложение как-то логически может знать о ключе. И тогда оно может подсказать роутеру в специальном хинте-комментарии этот ключ. Пример:

INSERT INTO test(id, age) VALUES (10, 16) /*__spqr__sharding_key: 30*/;

В общем виде, такие комментарии мы называем routing hints, их много, они разные.

Что происходит, если роутер не смог понять куда отправить запрос? Он явно возвращает ошибку приложению.

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

Для этого есть команда SYNC REFERENCE TABLE x. Роутер выберет случайный шард и с него скопирует таблицу на новый.

Каждый день я думаю о Римской Империи

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

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

Скорее, это набор независимых PostgreSQL-инстансов с умным/глупым роутингом запросов. SPQR не пытается быть полноценной распределённой СУБД с глобальными транзакциями и snapshot isolation - это отдельный, очень дорогой класс решений.

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

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

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

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

Если попробуете выполнить что-то вроде SELECT * FROM users; -- без WHERE по ключу шардирования, то явно получите ошибку. Это поведение управляется настройкой qrouter.default_router_behaviour.

Чтобы явно отправить запрос на все шарды (а не только на какой-то конкретный или на какую-то часть), есть хинт scatter_query:

SELECT * FROM users /* __spqr__scatter_query: true */;

Что произойдёт дальше:

  1. SPQR отправит запрос на все шарды параллельно

  2. Роутер получит результаты от каждого шарда независимо

  3. Результаты будут объединены и возвращены клиенту

Про ORDER BY, LIMIT, агрегатные функции и так далее. Прямо сейчас тут нет никакой логики обработки результата. Вот простой пример:

SELECT * FROM users LIMIT 1;
-- возвращается столько пользователей, сколько шардов.

Мы очень хотим что-то тут улучшить и поддержать, но пока изо всех сил держимся от написания кода, потому что никто из сообщства SPQR не просил об этом.

пользуясь случаем, если эта фича кажется вам интересной, можно спросить о ней в нашем чате в телеграм или создать issue на https://github.com/pg-sharding/spqr/issues

Вообще, есть еще много хинтов и настроек, которые управляют роутингом запросов. Подробнее можно почитать тут https://docs.pg-sharding.tech/routing/hints.

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

Насчёт горячего/холодного добавления или вывода шардов - не знаю, что именно ты вкладываешь в эти термины, поэтому просто опишу, как это устроено в SPQR.

Добавление нового шарда:

  • Разворачиваешь новый PostgreSQL-кластер. Поднимаешь сам инстанс, создаешь нужных пользователей и базы.

  • Как SPQR узнает о новом шарде? Варианта два: прописать новый шард в конфиге роутера, или вызвать в SPQR Admin Console команду ADD SHARD (WIP). Что выбрать - зависит от вашего способа деплоя.

  • Переносишь данные на новый шард. Если роутер смог подключиться к шарду, то нужно перенести данные: `SYNC REFERENCE TABLE` - если у тебя есть референсные таблицы, их надо синхронизировать; `REDISTRIBUTE KEY RANGE` - перенос данных шардированных таблиц.

Удаление шарда:

По сути то же самое, но в обратном порядке: переносишь данные с шарда с помощью REDISTRIBUTE, убираешь шард из конфига или DROP SHARD, удаляешь кластер.

Downtime

Во время redistribute: чтения не блочатся вообще, записи - практически без даунтайма (приложению может не повести попасть с изменением данных на перевозимый диапазон).

Я тоже, если честно, не встречал людей, которые сопровождали Vitess в проде. Я даже не уверен в курсе ли в YouTube, что они все еще используют Vitess (https://vitess.io/ -> who uses Vitess).

Всегда думал, что это скорее особенность моей небольшой эпсилон-окрестности, где MySQL не слишком популярен.

В общем, согласен, это все очень странно.

1

Information

Rating
Does not participate
Registered
Activity