Привет, меня зовут Владимир Сердюк. Я основатель компании SOFTPOINT и этой статьей хочу открыть цикл, посвященный распределенным кластерам СУБД с возможностью равномерного распределения нагрузки по всем его серверам.

Идеи создания распределенного вычислительного кластера СУБД (далее РВК) посещали меня достаточно давно. Если упрощенно описать, то программное обеспечение РВК позволяет объединить множество серверов в один суперсервер (кластер), осуществляющий равномерную балансировку всех запросов между отдельными серверами. При этом для приложения, которое работает на РВК все будет выглядеть как будто оно работает с одним сервером и одной базой данных (далее БД), это будут не разрозненные базы данных на распределенных серверах, а как будто одна виртуальная. Все сетевые протоколы, репликационные обмены, прокси-перенаправления будут скрыты внутри РВК. При этом будут эффективно и равномерно использоваться все ресурсы распределенных серверов, в частности, оперативная память и процессорное время.

Например, в облачном ЦОДе можно взять один физический суперсервер и нарезать его на множество виртуальных серверов СУБД. Но обратная процедура до настоящего момента была невозможна, т.е. нельзя взять много физических серверов и объединить их в один виртуальный суперсервер СУБД. В определенном смысле РВК это технология позволяющая объединять физические сервера в один виртуальный суперсервер СУБД.

Позволю еще одно сравнение, РВК – это все равно, что когерентная NUMA-технология, только для объединения SQL серверов. Но в РВК, в отличии от NUMA, за синхронизацию (когерентность) данных и частично оперативной памяти отвечает программное обеспечение, а не контроллер.

Для наглядности приведу схему привычного всем подключения клиентского приложения к серверу СУБД и сразу же схему с РВК. Обе схемы упрощенные, просто для понимания.

Идея кластера – децентрализованная модель. На рисунке выше proxy-сервер всего один, но в общем случае их может быть несколько.

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

После пяти лет исследований я детально проработал логическую архитектуру и протоколы взаимодействия и с помощью небольшой группы разработки создал рабочий прототип, который проходит нагрузочные тесты на популярной ИТ-системе 1С8.х под управлением СУБД PostgreSQL. СУБД может быть и MS SQL, и Oracle. Принципиально выбор СУБД не влияет на те идеи, что я приведу.

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

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

На тему партнерства пишите на адрес rvkpartner@softpoint.ru с комментарием «Партнерство по РВК».

На тему интереса внедрения продукта пишите на rvksales@softpoint.ru с комментарием «Внедрение РВК».

Содержание:

Для каких ИТ систем эффективен РВК

Стратегическая область применения

Почему нельзя для РВК использовать транзакционную репликацию

Механизмы (протоколы) обмена

Зачем нужен централизованный протокол в РВК

Механизмы обеспечения целостности и синхронности распределенных данных на уровне транзакций в РВК

Проблема распределенных деадлоков в РВК

Специфика администрирования РВК

Технологии параллельных вычислений как средство, повышающее эффективность использования РВК

План следующих публикаций по теме РВК

Для каких ИТ систем эффективен РВК

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

Таким образом, при условии, что запросы на чтение значительно превосходят по нагрузке запросы на запись, мы получаем приблизительно равномерное распределение нагрузки по серверам (нодам) РВК.

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

Изначально SQL планировался как язык, которым смогут пользоваться без навыков программирования и математики.

 

Вот выдержка из википедии:

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

На текущий момент можно утверждать, что навыки программирования для SQL все-таки нужны, но определенно минимальные. Большинство программистов изучали основы оптимизации запросов по верхам и того же Дэна Тоу «Настройка sql для профессионалов» в глаза не видели. Много логики по оптимизации запросов скрыто внутри СУБД.  Раньше, например, в MS SQL было ограничение в 256 объединений таблиц, сейчас в современных ИТ системах не редкость когда в запросе тысячи объединений. Широко и иногда слишком бездумно используется dynamic SQL, когда запрос формируется динамически. Поверьте, не существует математически точной модели построения оптимального плана выполнения сложного запроса. Эта задача чем-то похожа на задачу коммивояжёра и считается, что она не имеет точного математического решения.

 Вывод такой. SQL запросы эволюционно доказали свою эффективность и практически вся отчетность формируется на SQL запросах. Чего не скажешь про бизнес-логику и транзакционную логику. Любой из SQL языков оказался не очень удобным с точки зрения программирования сложной транзакционной логики. Он не поддерживает объектно-ориентированное программирование, имеет весьма неудобные логические конструкции. Поэтому можно сказать, что программирование разделилось на две составляющие. Написание разнообразных отчетов-запросов SQL, получение данных на клиента или сервер приложения и реализация остальной логики на прикладном языке приложения (не важно двухзвенка или трехзвенка). С точки зрения нагрузки на СУБД это выглядит как тяжелая SQL-конструкция на чтение и потом много маленьких на изменение.

Давайте теперь рассмотрим вопрос распределения нагрузки запросов Чтение-Запись на сервере СУБД по времени. Для начала нужно определится что значит нагрузка и как ее можно измерять?  Под нагрузкой будем понимать (в порядке приоритета описания): CPU (процессорная нагрузка), используемая оперативная память, нагрузка на дисковую подсистему. Основным ресурсом с точки зрения нагрузки будет CPU. Возьмем абстрактную OLTP систему и все SQL вызовы из множества параллельных потоков разобьём на две категории Чтение и Запись. Далее на основании средств мониторинга производительности, отобразим на графике интегральное значение, например CPU. Если усреднить значение хотя бы на 30 секунд, мы увидим, что значение графика «Чтение» в десятки, а то и сотни раз выше, чем значение графика «Запись».

Это обусловлено тем, что в единицу времени большее количество пользователей может запустить отчеты или макротранзакции, использующие тяжелые SQL конструкции, на чтение. Да, конечно, возможны задачи, когда система регулярно подгружает данные из очередей репликации, из внешних систем, запускаются регламентные процедуры закрытия периодов, запускаются процедуры бэкапирования. Но на основании нашей многолетней статистики (SOFTPOINT уже 20+ лет занимается решением задач производительности и масштабируемости баз данных) для подавляющего количества ИТ-систем нагрузка SQL-конструкций на Чтение превышает нагрузку на Запись в десятки раз.  Разумеется, могут быть исключения, например, биллинговые системы, в которых факт изменений фиксируется без какой-либо сложной логики и отчётности, но это легко проверить специализированным ПО и понять, насколько РВК будет эффективен для ИТ системы.

Стратегическая область применения

РВК на данный момент будет полезен, а, возможно, и жизненно необходим для крупных компаний с большими информационными потоками и мощной аналитической составляющей. Например, для крупнейших банков.  С помощью относительно небольших серверов можно составить РВК, который по мощности будет значительно опережать все существующие суперЭВМ. Разумеется, не будет одних плюсов. Минусом будет усложняющаяся часть администрирования распределённой системы и фиксированное замедление транзакций. Да, к сожалению, сетевые протоколы и логические схемы, которые использует РВК приводят к замедлению выполнения транзакций. На текущий момент целевым параметром является замедление транзакции не более 15% по времени.  Но еще раз повторю, что при этом система станет гораздо более масштабируемой, все пиковые нагрузки будут проходить без проблем и в среднем то же время транзакции будет меньше чем в случае использования одного сервера.  Поэтому если система не испытывает проблем с пиковыми нагрузками и стратегически этого не предвидится, РВК не будет эффективен.  В дальнейшем РВК после автоматизации административных процессов и оптимизации станет возможно также эффективен для средних компаний, потому как можно будет собирать мощный кластер даже из ПК с ssd (быстрыми, ненадежными и дешевыми) дисками. Его распределенная структура позволит без проблем отключать вышедший из строя ПК и на лету подключать новый. Система РВК контроля транзакций не даст некорректно записать данные. Также нельзя игнорировать геополитику, к примеру в случае отсутствия доступа к мощным серверам, РВК позволит собрать мощный кластер на базе серверов отечественных производителей.

Почему нельзя для РВК использовать транзакционную репликацию

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

Многие разработчики приложений, используя СУБД, даже не задумываются о том какие конфликты обращения к данным внутри движка решает система. Например, нельзя настроить транзакционную репликацию, добиться синхронности данных на множестве серверов и сказать, что это кластер СУБД. Данное решение не будет решать конфликт одновременного обращения к записи типа «Писатель-Писатель». Подобные коллизии непременно приведут к нарушению логики поведения системы. Также существующие протоколы транзакционной репликации обладают большими издержками, подобная система будет очень сильно проигрывать односерверному варианту.

Итого транзакционная репликация не подходит для РВК потому, что:

1.      Слишком большие издержки типовых протоколов репликации синхронной транзакцией.

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

2.      Не решается конфликт типа Писатель-Писатель

Конфликт возникает при одновременном изменении одних и тех же данных в разных транзакциях. По факту прошедшего изменения система «помнит» только абсолютное последнее изменение (или историю). Смысл SQL конструкции для последовательного применения теряется. Подобные конфликты в репликации иногда вовсе не имеют решений.

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

Проблема Писатель-Писатель принципиально не решается без proxy-сервиса на логическом уровне анализа SQL-трафика приложения.

Механизмы (протоколы) обмена

Полное архитектурное описание РВК будет приведено в отдельной статье. А пока ограничимся кратким, чтобы обозначить проблематику.

 

Все запросы к СУБД в РВК проходят через прокси-сервис. К примеру, на системах 1С он может быть установлен на сервер приложения. Прокси сервис понимает какой тип запроса Чтение или Запись. И если Чтение, то отправляет его на привязанный к пользователю(сессии) сервер. Если тип запроса Изменение, то отправляет его на все сервера асинхронно. При этом к следующему запросу он не переходит, пока не дождется положительного ответа от всех серверов. Если произошла ошибка, то она транслируется в клиентское приложение и откатывается транзакция на всех серверах. Если все сервера подтвердили успешное выполнение SQL конструкции, то только после этого прокси обрабатывает следующий клиентский SQL запрос.

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

Описанный выше алгоритм является основным протоколом, и мы его назовем зеркально- параллельным. К сожалению, этот протокол логически не для всех ИТ-систем может реализовать зеркально репликацию данных.

В некоторых случаях данные могут гарантированно отличаться в силу специфики системы, для этого реализован еще один протокол – «централизованный асинхронный», который гарантированно решает синхронную передачу информации. О нём в следующем разделе.

Зачем нужен централизованный протокол в РВК

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

А что, если нельзя этого делать по какой-либо причине?  Для решения подобных проблем вводится еще один протокол и сервер. Назовем его УсловноЦентральный. Далее будет понятно, что фактически центральным сервером он не является.

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

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

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

Механизмы обеспечения целостности и синхронности распределенных данных на уровне транзакций в РВК

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

UPDATE ТаблицаИтогов

SET Итог = Итог+Дельта

WHERE ИдТовара = Y. 

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

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

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

Проблема распределенных деадлоков в РВК

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

 

Для уменьшения распределенных деадлоков необходимо решить несколько технологических задач, одна из них – выделение различных физических сетевых интерфейсов под запись и чтение. Ведь если смотреть отношение CPU операций типа Чтения к Записи, то будет соотношение одного порядка, то для сетевого трафика тоже соотношение будет начинаться от двух порядков, более чем в сотни раз. Поэтому разделив на физически разные каналы сетевых коммуникаций эти операции (Чтение-Запись) мы сможем гарантировать определённое время доставки SQL запросов типа Запись на все сервера.

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

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

Подробнее будет в отдельной статье.

Специфика администрирования РВК

Администрирование распределенной системы, конечно же, сложнее чем локальной, особенно с требованиями работы 24*7. А все потенциальные пользователи РВК как раз и являются счастливыми обладателями ИТ-систем с режимом работы 24/7.

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

Технологии параллельных вычислений как средство, повышающее эффективность использования РВК

Для масштабируемой ИТ системы крайне важен высокий параллелизм процессов внутри базы данных. Для формирования параллельно отчетности как правило данный вопрос не стоит. Для транзакционной нагрузки в силу исторических рудиментов неоптимальной архитектуры возможны блокировки на уровне изменения одних и тех же записей (конфликт писатель-писатель). Если ИТ систему можно менять, есть открытый код, то можно оптимизировать систему. А если система закрытая, что делать в этом случае? В случае использования РВК появляются возможности на уровне администрирования обходить подобные ограничения. Ну или по крайней мере расширить возможности. В частности, с помощью настроек давать возможность изменять одну и ту же запись, не дожидаясь фиксации транзакции, если возможно грязное чтение, конечно. При этом, в случае отката транзакции данные об изменениях в хронологической последовательности также откатываются.

Подобная ситуация точно подходит, например, для таблиц с агрегацией итогов. У меня уже есть решения для данной проблемы, и я считаю, что независимо от использования РВК, необходимо расширить административные настройки СУБД, как Postgres, так и MSSQL (на ORACLE не исследовал вопрос).

Подробности – в отдельной статье.

Также необходимо раскрыть тематику грязного чтения в РВК и возможные с учетом этого небольшие доработки – внедрение виртуальных блокировок (компания SOFTPOINT запатентовала их как гибкие блокировки).

План следующих публикаций по теме РВК

Статья 2. Результаты нагрузочного тестирования РВК.

Статья 3. Почему для РВК нельзя использовать транзакционную репликацию?

Статья 4. Краткое архитектурное описание РВК

Статья 5. Зачем нужен централизованный протокол в РВК?

Статья 6. Механизмы обеспечения целостности и синхронности распределенных данных на уровне транзакций в РВК.

Статья 7. Проблема распределенных взаимоблокировок в РВК.

Статья 8. Специфика администрирования РВК

Статья 9. Технологии параллельных вычислений как средство, повышающее эффективность использования РВК

Статья 10. Пример интеграции РВК с 1С 8.х

 

Комментарии (28)


  1. vlad4kr7
    27.08.2024 22:06

    Проблема Писатель-Писатель принципиально не решается без proxy-сервиса на логическом уровне анализа SQL-трафика приложения.

    Извините, но это не так.

    SET Итог = Итог+Дельта

    Таких алгоритмов в принципе не существует, ...

    просто добавить Итог в условие, или поле версии - инкремент

    Много читать, еле осилил, но так и не нашел:
    - Master-Master, подразумевает возможность записи на любой мастер. У вас один вход в прокси.
    - в двух словах - САР теорему как решили?


    1. remoteadmiral Автор
      27.08.2024 22:06

      Про Писатель-Писатель комментария не понял.

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


      1. vlad4kr7
        27.08.2024 22:06

        нельзя настроить транзакционную репликацию, добиться синхронности данных на множестве серверов и сказать, что это кластер СУБД. 

        кроме того, что можно, так вы сами это и делаете.

        то что вы рассказываете - старый добрый 2РС, и его ХА транзакции.

        При параллельном выполнении от всех серверов на всех серверах - очень быстро заканчиваются коннекты.

        Короче, как делают:

        Если заменить ваш хэш на серийный номер транзакции, как в РАФТ протоколе, не исключает хеш, как дополнительную проверку. Прокси сделать в виде GTC - Global Transaction Coordinator, который определяет мастера. Все сервера - могут писать, если сервер падает, то падают подключенные клиенты и выполняемые транзакции. клиенты переподключаються, и перевыполняют транзакции, так-же как в без кластерном варианте... я не буду цикл стаей делать, бета кластера доступна и бесплатна.

        1. Ванильный постгрес со всеми транзакциями

        2. Переезд на кластер и обратно, без копирования данных

        3. Почти линейная масштабируемость


        1. remoteadmiral Автор
          27.08.2024 22:06

          Я человек простой). Вы на вашем(описанном) решении сможеет запустить 1С 8.х, равномерно распределить нагрузку по физическим серверам постгрес? Если да, то я могу вам клиентов набросать) Да и сам за реализацию заплатил бы, что бы посмотреть. Мы например проводим нагрузочные тесты, скоро будем запускать первые внедрения.


          1. vlad4kr7
            27.08.2024 22:06

            Я с 1С не работал, лет 20. Если клиенты разные - то или на DNS балансировать, или Т3 урл, клиент будет выбирать сервер.

            "бета кластера доступна и бесплатна", обращайтесь


            1. remoteadmiral Автор
              27.08.2024 22:06

              написал в личку, готов к дискуссии, готов посмотреть если что то есть готовое. Пока, что аналогов не видел.

              Свое решение могу показать на стенде.


          1. PAL_habr
            27.08.2024 22:06

            Не понял, а чем относительно стандартная реализация построения кластер высокой доступности для постгре не устраивает? Postgresql, patroni, etcd, keepalived, haproxy, pgbouncer.. Стандартная потоковая репликация (асинхронная или синхронная), лидер (запросы на запись/чтение) и несколько реплик (запросы на чтение)

            Как один из вариантов:

            https://its.1c.ru/db/metod8dev/content/5971/hdoc


            1. remoteadmiral Автор
              27.08.2024 22:06

              Тем что мастер-мастер не позволяет сделать кластер, тем что транзакционную нагрузку не позволяет распределять.


              1. PAL_habr
                27.08.2024 22:06

                Какой ещё "мастер-мастер". Вы пишите, что у вас транзакции (т.е. запросы на изменения) передаются сразу на все серверы. Здесь никакого "распределения" нет. Стандартная репликация в постгре работает практически так же, но быстрее - транзакция выполняется на мастере (формируется план выполнения и т.п.) а на реплики передаётся wal-файлы, который там проигрывается (асинхронно или синхронно). Всё распределение нагрузки в таких кластерах (как и у вас) - это только распределение нагрузки по чтению.

                Мульти-мастер читал собирали на mysql - это когда разные запросы на изменения могут принимать разные ноды (например нода в Европе и нода в Азии) и потом делать синхронизацию в обе стороны.

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


                1. remoteadmiral Автор
                  27.08.2024 22:06

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


                  1. PAL_habr
                    27.08.2024 22:06

                    Я прочитал, что запросы на чтение у вас распределяются неким образом. Но вы видимо невнимательно прочитали мой первый пост. В стандартных схема построения HA-кластера для постгре это давно реализуется достаточно стандартными решениями (я вам даже ссылку привёл. Там, вроде про это тоже говорится.. Причём на примере кластерах для 1С).

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


                    1. remoteadmiral Автор
                      27.08.2024 22:06

                      Да нет, мне кажется это как раз вы поверхностно читаете описания подобных решений. Я открыл вашу ссылку. Там название Построение отказоустойчивого PostgreSQL. Ну так это совсем про другое. Отказоустойчивость и горизонтальное масштабирование это разные вещи. Уверен вы не найдете в описании каким образом балансируются запросы в рамках транзакций. На базе отказоустойчивого кластера можно сделать перенаправление каких либо отчетов(мы давно делали для always on - Microsoft) , транзакционной нагрузки -никогда!


                      1. PAL_habr
                        27.08.2024 22:06

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

                        Отказоустойчивый кластер - это общепринятое название кластера с высокой доступностью (примерно то что вы у себя обозначаете 24/7).

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

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

                        Вы почитайте про то как данные синхронизируются в постгре, что такое потоковая синхронизация, асинхронная, синхронная, причём здесь wal-файлы, что такое patroni и как он связан с etcd или consul, посмотрите схемы построения кластеров постгре и т.д. Может окажется, что не нужно городить огороды на ровном месте.


                      1. remoteadmiral Автор
                        27.08.2024 22:06

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


                      1. PAL_habr
                        27.08.2024 22:06

                        Какими "регалиями на тему репликации"? Максимальная "регалия" в такой теме (если вы не пишите свою субд) - это "я умею настраивать репликации" :)


                    1. remoteadmiral Автор
                      27.08.2024 22:06

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


                      1. PAL_habr
                        27.08.2024 22:06

                        Вы как-то путаетесь в терминах. Это кластер бывает отказоусточивым, а не нода. Думаю, что никакой "отчёт" вы никуда не "перенаправите", если у вас нода с этим "отчётом" перестала работать.

                        А по поводу временных таблиц в 1с.. Вы правы, я не специалист в тонкостях работы 1С и даже не могу назвать себя специалистом в кластерах, но.. Вы всё же невнимательно прочитали статью по ссылке. А она была именно про 1С (о чем я вам сказал). Почитайте там раздел: Использование резервного сервера PostgreSQL для механизма копий базы данных. Возможно в нем есть ответы на ваши вопросы. ;)

                        "Какой-то там кластер" - серьёзное утверждение для кластеров на ПО, используемых Red Hat, IBM Compose, Zalando и др..

                        Кстати, Mazars, тоже использовала patroni для организации кластер для 1с (порядка 200 баз, как они писали) .. по крайней мере в 2021ом.

                        P. S. : читайте более внимательно и возможно..... не потребуется городить огородов на ровном месте ;)


                      1. remoteadmiral Автор
                        27.08.2024 22:06

                        Я обладаю техникой быстрого чтения) Читаю быстро но вдумчиво. Разумеется раздел про механизма копий БД я прочитал сделав на нем акцент. Ответов на мои вопросы в нем нет. Вы просто бросаете ссылки и не готовы погружаться в детали.

                        Хотите авторитетом давить?(авторитетом ссылок))) нут так вот ниже ссылочку привел - "По результатам российского конкурса Microsoft среди партнеров, компания SOFTPOINT с решением DATA CLUSTER была признана лучшей компанией в номинации “Data Platform Solution”, подтвердив тем самым высокую экспертизу в области ИТ- решений для бизнеса. " Так это решение до сих пор продается, аналогов не знаю. Если есть - покажите. Я вот лично готов показать, привести референсы. К слову с этим решением вышли в финалисты международные , если не ошибаюсь, вместе c HP(в Вашингтоне поздравляли). А вы при этом хотите меня убедить, что я не разбираюсь совсем в кластерах) Вы сами себя ограничиваете в новых знаниях.

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

                        Механизм копий баз данных имеет особенность в использовании внешнего типа репликации данных при размещении данных в PostgreSQL. Особенность связана с тем, что резервный сервер PostgreSQL доступен только на чтение, включая временные таблицы. Такое ограничение приводит к тому, что запросы к СУБД, с созданием временных таблиц, выполняемые 1С:Предприятие, будут завершаться с ошибкой.
                        Для снятия этого ограничения требуется развёртывание дополнительного кластера PostgreSQL, доступного для записи данных. Ниже будет описан пример развёртывания такого сервера.

                        и дальше описания инсталляций...


                      1. PAL_habr
                        27.08.2024 22:06

                        Читал про ваш data cluster. По описанию за мульт в год предлагается что-то вроде бесплатного haproxy (в лучшем случае в комбинации с keepalived) при стандартно развёрнутом кластере postgresql или кластере mssql. При этом, вы уж извините, описание на сайте такое же технически корявое, как и статья. И никакой конкретики. Есть термины always on и потоковая репликация, которые относятся к стандартным механизмам построения кластером от ms и к репликации постгре (про это я вам писал, кстати), но именно про само решение практически ничего технического не сказано - общие слова. Смешали всё в кучу, описали стандартную схему построения кластер высокой доступности для двух субд и при этом, про само решение - что это и чем это отличается от чего-то стандартного так ничего и не сказали (с технической точки зрения).

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

                        По поводу "горизонтального масштабирования".. Вы серьёзно не понимаете что это такое или чисто шутите? Для примера ссылки не нужны. Кластер сам по себе это и есть штука, которая придумана для "горизонтально масштабирования" системы. Добавляете ноду, перераспределяете нагрузку (в данном случае добавляете ещё один сервер, который может обрабатывать запросы на чтение) и тем самым горизонтально масштабируете систему. ..я про это выше писал, но вы, видимо, это пропустили.

                        ..на всякий случай:

                        Высокодоступность - это про то, что умирание одной из нод позволяет системе продолжать работу.

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

                        На всякий случай приведу ещё одну ссылку, где тоже присутствуют технические описания и схемы про кластеры постгре и ms sql, но, скорее всего, для вас это тоже будет неинтересно и не убедительно :)

                        https://infostart.ru/1c/articles/1499932/

                        P. S. : когда техническая составляющая туманна - на первый план выступает хороший маркетинг ;)


                      1. gallam
                        27.08.2024 22:06

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

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

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

                        • Катастрофоустойчивость - это когда случается пожар, наводнение и прочее, то нода географически распределенная подхватывает обслуживание.

                        • Высокая производительность - это когда трафик от приложения распределяется между нодами, таким образом возрастает потенциал системы в плане обслуживания роста ИТ системы

                        В идеале чтобы кластер все это мог выполнять, но на практике первые 3 - с 4 есть проблемы, так как общие данные, синхронизации, блокировки и прочее. Так вот в статье описан 4 аспект кластеризации (сложности мастер-мастер, когда изменения идут на много нод одновременно).


                      1. remoteadmiral Автор
                        27.08.2024 22:06

                        А дискуссии не получается. Я не вижу никаких технических аргументов, поэтому даже затрудняюсь, что мне отвечать) А не технические аргументы - покажите у кого конкретно работает мастер-мастер кластер СУБД? - уважаемый оппонент делает вид, что не замечает. Поэтому вот такая у нас "дискуссия")


                      1. PAL_habr
                        27.08.2024 22:06

                        Да, что значит "мастер-мастер"?..

                        Мультимастер системы (в субд) - это не то, что Вы описываете, а системы которые имеют в кластере несколько узлов независимо принимающих все типы запросов (и на чтение и на изменение) и при этом обеспечивается целостность данных на уровне всего кластера (логику работы я вам тоже приводил). У вас же описана какая то система (даже не репликации), а синхронного выполнения запросов (т.е. выполнение запросов с подтверждением) на нескольких серверах. Это даже не вписывается в ни в кластер ms sql (с его always on) ни в кластер postgresql (с его потоковой репликацией) описанный в решении Data Cluster вашей же компании.

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

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

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

                        По приведенной цитате сразу возникает куча вопросов, но самы "толстый" - это: т.е. если один из допустим 10 серверов не смог выполнить запрос (место на диске закончилось или сетевой порт умер), то вместо того чтобы исключить этот сервер как неработающий, предлагается просто парализовать работу всех других серверов.. Офигенное решение! Поставить 10 серверов, чтобы отказ одного остановил работу всей системы.

                        Про скорость работы такого решения можно даже особо не говорить: построение плана выполнения запроса - везде, дополнительные затраты на анализ и модификацию запросов.. Похоже, что всё, что у вас выполняется по плану - ограничено простейшими update, insert, delete и select. О хранимых функциях, тригерах, динамическом построении запросов речи здесь вообще не будет.

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

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

                        Кстати, как организовывается у вас отказоустойчивость самой вашей оболочки (или того же Data Cluster) тоже ничего нет (технического описания).


                      1. remoteadmiral Автор
                        27.08.2024 22:06

                        Ну, это попытка, что то осмыслить в моих утверждениях;)

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

                        Первое, с чего мы начали - почему вы привязались к репликации? Если мы говорим про триггеры, очереди и т.п. так она не единственный и далеко не самый эффективный способ переноса информации. Я к слову изначально рассматривал триггеры с сокетами для синхронизации - увы по производительности большие просадки.

                        Зеркалирование сетевых SQL пакетов на изменение самый быстрый способ - но имеет коллизии. Для этого кстати есть дублирующий чисто репликационный (централизованный) механизм. Почему не расписал детальней ? Потому что в планах опубликовать статью посвященную только транспортным механизмам.(минимум страниц на 10-ть)

                        Второе, ответьте на вопрос - вы правда считаете, что основную нагрузку на систему дают запросы на изменение? Сначала определитесь с этим вопросом, иначе все остальное бессмысленно обсуждать.

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


                      1. PAL_habr
                        27.08.2024 22:06

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

                        Зеркалирование запросов на все серверы в общем случае (даже если всё там просто с запросами) не является "самым быстрым способом". Почему? Дело в том, что т.к. у вас используется механизм подтверждения выполнения запроса всеми серверами (как - вопрос десятый), то время выполнения запроса с точки зрения сервера приложений будет определяться временем выполнения запроса самым медленным сервером (это если ничего не упадет. если упадет - то всё вообще встанет). Почему будут быстрые и медленные серверы если они одинаковые? Ну, самый явный ответ такой. Т.к. в вашей системе запросы на чтение перераспределяются между разными серверами, то состояние памяти, кэшей, загрузки процессоров, буферов ввода/вывода и т.п. будет на серверах разное, и кому-то не нужно будет читать данные с дисков для выполнения запроса, а кому-то нужно (если очень просто).
                        В стандартной схеме репликации (допустим синхронной) всё гораздо проще и быстрее. На мастере строится план выполнения запроса (у вас он будет строиться каждым сервером самостоятельно). Запрос выполняется, но транзакция не закрывается. При выполнении формируется WAL-файл, который передается на все серверы-реплики. Серверы реплики проигрывают этот файл (это не выполнение запроса, а уже гораздо более быстрые операции со страницами данных, индексов и т.п.). Если всё ок - то передается подтверждение о том, что транзакция выполнена. Мастер получив подтверждения закрывает транзакцию (делает у себя commit). Примерно так.

                        2. Чаще всего, пожалуй, основную нагрузку (в части системы ввода/вывода например) будут создавать запросы на чтение (просто в силу того что чаще всего их больше). Я с этим и не спорил :)
                        Но это, тоже кстати, не всегда. Могут быть системы в которых это не так. Допустим, чисто гипотетически, какая-то система хранения сырых данных, поступающих с датчиков мониторинга, где сами сырые данные практически для доступа не используются.
                        Но, ещё раз, балансировка/распределение запросов на чтение между всеми нодами кластера - это тоже достаточно стандартная процедура (и я вам тоже про это писал). :)

                        3. То, что у вас равномерно нагружаются все ноды, к сожалению, не говорит о том, что работают они эффективно, а просто говорит о том, что они выполняют одну и ту же работу.

                        Объясню в чем разница. Пусть каждая ваша нода может выполнять 10 операций в единицу времени. И пусть операция добавления одной записи занимает 6 операций, операция репликации занимает 4 операции (я уже писал, почему это быстрее простого выполнения запроса выше), а операция чтение - 2 операции.

                        Фишка в том, что в вашем случае каждая из нод потратит по 6 операций на добавление и у каждой останется по 4 операции на выполнение, допустим, 2 чтений. Ноды будут загружены равномерно.

                        В случае репликации мастер нода потратит те же 6 операций, и у неё останется 4 операции для 2х чтений, но остальные ноды потратят по 4 операции и у них останется по 6 операция для 3х чтений.. Ноды (в свете операция добавления записей), конечно по графику будут загружены неравномерно, но эта неравномерность будет говорить о том, что большинство нод могут сделать больше работы (например обработать больше запросов на чтение)

                        ...такие вот простые рассуждения

                        P.S.: под "не идемпотентным" в данном случае понимается запрос, который при выполнении на разных серверах будет давать разный результат


                      1. remoteadmiral Автор
                        27.08.2024 22:06

                        Ну насчет проверки на результат тут все понятно, парсинг, в контексте 1С, как правило никаких ошибок. Если бы была сложная система с хранимками , то там собирается своего рода база знаний. И вот если произошла ошибка то при проверке завершения транзакции проверяется состав хэш суммы(это как раз триггеры делают) и если он не совпадает (это как раз произойдет когда чтение -запись перепуталась в хранимке например) то транзакция откатывается с ошибкой. По идее это будет происходить редко, после этого в базу знаний эта ошибка записывается и в дальнейшем она пойдет по централизованному алгоритму. В котором подобных коллизий быть не может. Это если вкратце.

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

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


                      1. PAL_habr
                        27.08.2024 22:06

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

                        а "практика и бизнес", они, как ни странно, разные бывают. бывает, что и микроскопами гвозди забивают, а потом радуются как эффективно это было сделано. ;)

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

                        в любом случае, успехов :)


                      1. PAL_habr
                        27.08.2024 22:06

                        Все 4 описанных вами сценария реализуются по достаточно стандартным схемам. "Катастрофоустойчивость" по сути отличается только размещением узлов кластер, а производительность обеспечивается, как минимум, распределение запросов на чтение для кластеров с одним мастером/лидером) или всех запросов для кластеров с несколькими мастер-узлами (я писал про это.. там где про Европу и Азию).

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

                        Подробнее - смотри комментарий ниже.


  1. remoteadmiral Автор
    27.08.2024 22:06

    (320) Решения SOFTPOINT для Microsoft World Partner Conference - YouTube

    это кстати нашей компании другое давнишнее решение под MSSQL, что бы вы не думали что новички