SoftPoint Data Cluster (Решение задачи масштабируемости СУБД MSSQL с помощью межсерверной кластеризации)-14.11.2012-   

   

Решение задачи масштабируемости СУБД MSSQL с помощью межсерверной кластеризации

   1.Основные подходы к реализации межсерверной кластеризации для серверов MS SQL

   2.Зеркалирование и логшиппинг

   3.Репликация данных

   4.Softpoint Data Cluster

 

Решение задачи масштабируемости СУБД MSSQL с помощью межсерверной кластеризации

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

Не для каждого приложения вообще это технически возможно.

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

  1. Возможна временная рассинхронизация данных на серверах кластера в момент интенсивной нагрузки (для асинхронных методов реплицирования данных).
  2. Для синхронных методов более длительное время выполнения транзакций на изменение данных при  минимальных нагрузках.
  3. Отсутствие общего блокировочного пространства.
  4. Снижение линейной скорости при минимальных нагрузках за счет дополнительных издержек на управление кластером
  5. Возможность возникновения распределенных деадлоков, в некоторых случаях нарушения целостности данных.
  6. Длительная процедура подключения дополнительного сервера в кластер. Необходимо первоначально синхронизировать БД.
  7. Не каждое приложение возможно адаптировать под работу в кластере (архитектура, специфика структуры, специфика запросов, закрытость кода и т.п.)
  8. Детерминизм данных. Например, отличие в предопределенных значениях  на серверах , getdate(), guid() и т.п.

1.Основные подходы к реализации межсерверной кластеризации для серверов MS SQL. 

  1. Зеркалирование,  логшиппинг.
  2. Зеркалирование в режиме alwayson для серверов MS SQL 2012
  3. Репликация транзакцией (как один из вариантов репликации данных).
  4. Синхронизация БД на уровне провайдера доступа к MS SQL (Softpoint Data Cluster).

Общее описание

Перед рассмотрением вариантов кластеризации хотелось бы поднять один очень важный вопрос. В любой ИТ на базе СУБД MSSQL системе существуют запросы приводящие к изменению данных их будем называть запросы на изменение.  Также существуют запросы, не приводящие к изменению данных – их будем называть запросы на чтение.  В подавляющем большинстве случаев для бизнес-приложений  отношение нагрузки на сервер со стороны запросов на чтение больше в десяток раз,  чем нагрузка от запросов на изменение. За счет этого возможна балансировка и масштабирование нагрузки. Обеспечив синхронное состояние данных на различных серверах, возможно направлять запросы на чтение равномерно по всем серверам кластера.  Если же относительная нагрузка запросов на изменение высока, то в данном случае необходимо рассматривать вопрос распределенного хранения данных, впрочем, это тема для отдельной статьи.  Итак, в этой статье будем рассматривать случаи, в которых отношение нагрузки от запросов на чтение будет значительно больше, чем от запросов на изменение.  

 

Практика (получение нагрузки со стороны запросов): для определения нагрузки MS SQL со стороны запросов на чтения и запросов на изменения можно использовать инструмент MS Profiler. Для этого необходимо сделать следующее:

1. Собрать все запросы от вашей информационной системы к серверу СУБД за небольшой, но «показательный» промежуток времени (например, за 1 - 2 часа работы). С каждым собранным запросом должны быть доступны следующие параметры (CPU, Reads, Writes), которые являются показателями потребления ресурсов MS SQL на выполнения запроса.

2. Разделить полученные запросы на 2 группы (на чтения и на изменение), и посчитать для каждой группы суммарное значение CPU, Reads, Writes.

Вывод: таким образом можно ориентировочно оценить нагрузку со стороны запросов на MS SQL. Точность этой оценки зависит от правильности критерия определения принадлежности запроса к группе, от правильного выбора «показательного» периода для сбора информации.

2.Зеркалирование и логшиппинг.

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

Все изменения данных фиксируются и накапливаются в журнале транзакций сервера          MS SQL.  Имея несколько синхронных баз данных на определенный момент времени, возможно, сбрасывать очередную порцию измененных  данных из журнала транзакций основной БД (БД источник) и применять эти изменения на дополнительных (БД приемник).

Сначала рассмотрим логшиппинг.

Первоначально настраиваются две синхронные БД. Например, из бэкапа. Затем настраивается задание MS SQL, с помощью которого по расписанию переносится очередная порция измененных данных из журнала транзакций. Периодичность переноса событий журнала транзакций можно настроить любую (хоть раз в одну минуту). Таким образом, удается поддерживать зеркальную БД с небольшим отставанием от рабочей (основной БД).  Какие возникают при этом сложности? Первая, несущественная, это то, что с базой можно работать только на чтение. Основная же проблема, это то, что в момент восстановления очередной порции из журнала транзакций никто не может работать с базой. То есть, база должна быть явно переведена из состояния «read only» в состояние «recovery». Исходя из этого условия, ценность этого механизма для балансировки нагрузки резко падает.  Тем не менее, какие существуют возможные варианты решения этой проблемы?

Распишем эти проблемы более подробно.

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

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

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

                Что касается технологии зеркалирования - Mirroring (до версии MS SQL 2012) – пакеты передаются не заданиями MS SQL Agent как логшиппинг, а через прямые соединения с MS SQL в кластере. И, что еще важнее, дополнительная БД (приемник) никогда не переходит в состояние «read only» - таким образом, мы не имеем возможность распределять нагрузку. Решается только задача надежности.

                Принципиальная схема технологий логшиппинга и интеграция с приложением показана на рисунке ниже:



3.Репликация данных.

                Существуют различные виды репликаций: snapshot (репликация снимком), transactional (репликация транзакций), merge (репликация слиянием). Каждая из них имеет свое применение, свои преимущества и недостатки, но для кластера наиболее подходящая – репликация транзакций, обеспечивающая требуемый уровень оперативности и целостности данных.

                Концептуальное  описание репликации транзакцией.

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

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

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

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

                Рассмотрим основные минусы и плюсы данного вида кластеризации.

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

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

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

Существуют и технические  сложности.

 

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

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

Варианты минимизации времени рассинхронизации в транзакционной репликации.

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

Рассмотрим пример:

Предположим, есть транзакции:

LSID =125(update table1 set Z=1 where id>1 and id<1000000; update table2 set X=5 where id=1) ,

LSID =126(update table3 set Z=1 where id=1000001; update table2 set X=5 where id=1)

            В этом случае первая транзакция изменяет миллион записей из таблицы table1, а затем меняет одну запись в таблице table2 на значение 6. Вторая транзакция меняет одну запись в таблице table3  и затем меняет одну запись в таблице table2 на значение 5. Если эти транзакции будут применяться последовательно, то никаких проблем не будет. Если же в целях ускорения эти транзакции будут выполняться параллельно в различных потоках  - возникнет рассогласование данных. В данном примере очевидно, что не смотря на то, что стартует раньше транзакция LSID =125, раньше выполнится update table2 set X=5 where id=1 транзакции с LSID =126, чем аналогичный update  транзакции LSID =125. Это произойдет, потому что в транзакции 125 выполняется первоначально изменение миллиона записей, а в транзакции 126 изменение всего одной записи. Если не предусмотреть разрешение этой ситуации – в этом случае в базе подписчика X будет равняться «6» вместо правильного значения «5».

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

1)       Параллельный старт транзакций с фиксацией в хронологическом порядке.

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

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

Какие в данном подходе существуют проблемы?

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

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

            2)      Параллельный старт транзакций с использованием блокировочного механизма. Этот подход перенимает в себя полностью первый подход, с тем отличием что для минимизации затрат «холостых откатов» можно применить блокировочные механизмы.

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

3) В случае если изменений в очереди накопилось достаточно много – возможно транзакции объединять между собой при этом группировать изменения в объектах таким образом, что бы они в принципе не могли вступить друг с другом в конфликт.  Например, группируя записи в разрезе таблиц или секций таблиц. Так как в транзакционной репликации в очереди изменений есть таблица и идентификатор записи – сделать это совсем не сложно. Запрос на подобную группировку будет отрабатывать значительно быстрее, чем принятие самих изменений. Затем эти изменения можно применять, используя много потоков. Конечно, могут возникнуть дополнительные сложности с разрешением конфликтов, но они решаемы.

                Общая схема технологии репликация транзакции приведена ниже:


4.Softpoint Data Cluster.

   Существуют 2 варианта реализации программного кластера Softpoint Data Cluster: кластер на базе технологии Always On MS SQL 2012 и на базе собственного координатора Softpoint. В первом варианте (на основе Always On) все запросы к серверу БД разделяются на две группы: запросы на чтение и запросы на изменение данных. Запросы на изменение поступают на основной сервер БД, а запросы на чтение распределяются между дополнительными серверами в зависимости от их нагрузки. Учитывая, что в большинстве информационных систем нагрузка от запросов на чтение намного больше, чем нагрузка от запросов на изменения данных, получаем высокую доступность основного сервера БД для оперативной работы даже в периоды интенсивной работы.

   Ниже приведена архитектура этого решения.

 

    Таким образом, высокую доступность серверов баз данных и синхронизацию обеспечивает технология Always On MS SQL 2012, а эффективное распределение нагрузки и простоту использования в приложениях - Softpoint Data Cluster.

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

  

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

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

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

   На практике возникает множество технических проблем.  

   Рассмотрим технически более подробно каким образом устроен кластер.

   Все запросы и подключения, которые попадают на SQl сервер, проходят сначала через координатор.  Это получается своего рода виртуальный SQL сервер.  Его цель  - координация подключений, определение запросов на чтение и запись, установление и координация единой хронологии выполнения транзакций на всех серверах.

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

  Рассмотрим более подробно запросы на изменение.

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

   Рассмотрим на примере зачем нужна четкая хронология выполнения операций на всех серверах кластера.

   Предположим, выполняются две конкурирующие операции стартующие с минимальным интервалом времени.  Предположим, в одной сессии выполняется конструкция update table1 set x=5 where id=1, а в другой сессии выполняется конструкция update table1 set x=6 where id=1. Также будем считать, что эти конструкции выполняются в рамках достаточно длительных транзакций, а разница во времени старта этих конструкций минимальна.  Если эти конструкции будут выполнятся на одном сервере, то ничего страшного не произойдет. Первая успевшая сессия выполнит update и, таким образом, захватит соответствующий ресурс. Вторая опоздавшая сессия будет ожидать разблокировки ресурса, то есть завершения транзакции. В случае если эти конструкции будут выполняться на кластере серверов, все гораздо сложнее и хуже. Предположим, в кластере два сервера. Если на обоих серверах эти конструкции выполнятся в одной и той же последовательности, все будет хорошо.

Например, 

Сервер1 update table1 set x=5 where id=1, update table1 set x=6 where id=1

Сервер2  update table1 set x=5 where id=1, update table1 set x=6 where id=1

Или

Сервер1 spid 100(update table1 set x=6 where id=1), spid 101(update table1 set x=5 where id=1)

Сервер2  spid 100(update table1 set x=6 where id=1), spid 101( update table1 set x=5 where id=1)

В этом случае все хорошо.

Гораздо хуже, если последовательность операций не будет совпадать.

Например,

Сервер1  spid 100(update table1 set x=5 where id=1), spid 101(update table1 set x=6 where id=1)

Сервер2  spid 101(update table1 set x=6 where id=1), spid 100( update table1 set x=5 where id=1)

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

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

   На Сервер1 spid 100 будет ожидать spid 101. На Сервер2 spid 101 будет ожидать spid 100. А также spid 100 на Сервер1 будет ждать завершения транзакции на spid 100 Сервер2. А spid 101 на Сервер2 будет ждать завершения транзакции на spid 101 Сервер1.  Получается распределенный дедлок, который не разрешится автоматически SQL сервером.  Для разрешения подобных распределенных дедлоков необходимо будет получать данные о блокировках со всех серверов, а затем генерировать соответствующий эксепшн, отменяя транзакцию как минимум на одном из них. Например, через слепки sysprocesses.  Подобный координатор хоть и позволит решить проблему, но очень сильно просадит производительность системы. Поэтому единственным эффективным решением будет максимально сократить вероятность распределенных  дедлоков.

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

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

   Одной из проблем синхронного кластера является минимизация времени выполнения распределенных транзакций. Для достижения этой цели необходимо, чтобы  незакомиченные изменения  применялись максимально оперативно.  То есть, все изменения необходимо применять одновременно на всех серверах кластера. Задача применения все изменений синхронно на  всех серверах  возможна только с помощью «Softpoint Data Cluster». Но возможны варианты проще. Один из серверов будет являться эталоном. После того как изменения все прошли но еще не был выполнен commit, они передаются на все остальные сервера кластера и начинают там применяться. При этом транзакция на «эталонном» сервере не закрывается до тех пор пока все транзакции не подтвердятся на всех серверах кластера.  Реализовать это было бы возможно, реализовав logreader журнала транзакций, при этом интегрировав с клиентским приложением, либо реализовав перехват провайдера (для управления транзакциями). Также можно реализовать подобное в случае транзакционной репликации. Потому как в этом случае аналог logreadera можно реализовать самостоятельно.  Но при этом остаются все те же вышеописанные проблемы. Необходимо обеспечить   одинаковый порядок выполнения изменений на всех серверах, при этом реализовать многопоточность с минимальными издержками на координирование потоков.  За кажущейся простотой формулировка - это совсем не тривиальная задача.

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

   Мало-реализуемые идеи.

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

 

   Самое последнее решение - «Softpoind Data Cluster». В этом случае реализован синхронный кластер,  в котором линейное падение скорости применения транзакций минимально.  Специфика этого решения в том, что оно не требует дорогостоящей поддержки, а также требует минимальной адаптации с приложением.

Подробнее о решении читайте здесь:

Softpoint Data Cluster – программный кластер MS SQL Server 2012 для 1С 8.2 (на основе технологии Always ON)

Для удаленного тестирования решения на нашем тестовом стенде обращайтесь по e-mail softpoint@softpoint.ru  или по телефону +7(495)-543-74-02  

Статья: SoftPoint Data Cluster (Решение задачи масштабируемости СУБД MSSQL с помощью межсерверной кластеризации)-14.11.2012-

Перейти на главную страницу компании "Софтпоинт"