Взаимодействие с данными с использованием нескольких баз данных / серверов


18

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

Например:

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

На этот вопрос лучше ответить на администраторов баз данных . Здесь тоже нет ничего плохого, так что я просто проверю моды на DBA. Если это подходит там, вы бы хотели мигрировать?
Адам Лир

@ AnnaLear - я думаю, это зависит от ответов. На данный момент меня больше интересует прикладная сторона вопроса, так что пока, я думаю, что здесь может быть лучше.
VirtuosiMedia

@AnnaLear ack, тогда согласитесь с OP, если они хотят, чтобы конкретный код приложения.
Jcolebrand

Ответы:


13

Хорошо, давайте разберемся с этим:

  • Как строятся соединения между двумя таблицами в нескольких базах данных? (Пример кода здесь будет полезен).

Это довольно просто. Объекты SQL имеют соглашение от 1 до 4:

Servername.databasename.schemaname.tablename

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

Select a.*,b.* from 
tableA a inner join 
tableB b on a.col1=b.col1

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

Select a.*,b.* from 
tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

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

Select a.*,b.* from 
databaseD..tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

Если вы используете разные схемы и / или владельцев, вы можете добавить их в:

Select a.*,b.* from 
databaseD.john.tableA a inner join 
databaseC.accounting.tableB b on a.col1 = b.col1

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

Select a.* from 
databaseD.john.TableA a inner join 
ATLANTA.databaseC.accounting.tableB b on a.col1 = b.col1
  • Когда пора выходить за рамки настройки 1 базы данных / 1 сервера? Насколько часто это нужно делать? Существуют ли какие-либо специальные стратегии для отслеживания того, какие таблицы находятся в какой базе данных?

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

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

Что касается того, когда и почему необходимо выйти за пределы одной базы данных. Обычно это сочетание бизнес-правил, политики и / или технических причин.

Например, там, где я работаю, у нас есть 16 баз данных, распределенных по 4 серверам. У нас есть MainDB, ImageDB, referencetableDB, HighvolumeTransactionDB, ReportingDB, StagingDB, ProcessingDB, ArchiveDB, FinancialDB. Чтобы привести несколько примеров того, почему они разные:

  • FinancialDB, конфиденциальная информация
  • Образ БД, конкретные требования к хранению и восстановлению
  • ReferenceDB, низкая транзакция, высокое чтение
  • ReportingDB, с очень высоким чтением, должен быть восстановлен / реплицирован в различные другие среды в отличие от многих других данных
  • StagingDB, ничего постоянного, просто усиленная база данных, над которой мы имеем больше контроля
  • MainDB, взаимодействует со всеми другими БД, но требует дифференциального резервного копирования, так что ... мы разделили
  • Таблицы HighVolumeTransaction (которые являются относительно переходными) к собственной БД, чтобы сохранить разумный размер резервной копии.
  • Архив, множество одних и тех же данных из Main и Reporting, но с более длительными периодами хранения и более сложными запросами, копающимися глубоко в данных. Если бы это все еще сочеталось с Main / Reporting, это привело бы к падению нашей системы.

Нужно ли коду приложения знать, что одна или несколько баз данных распределены по нескольким серверам? Если нет, то на каком уровне фильтруются запросы?

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

Оттуда им нужен контекст базы данных для выполнения в. Как правило, это будет наиболее часто используемый для приложения, может быть, даже оригинальный из одной базы данных / один серверный день приложения. Вы МОЖЕТЕ заставить приложение явно переключать контекст базы данных при каждом вызове, но это очень затрудняет настройку базы данных без изменения приложения.

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

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

Итак, для иллюстрации:

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

Итак, вы пишете звонок из вашего приложения:

Select c.ClientName, c.ClientAddress, s.totalSales,f.CreditBlance from
Clients c join Sales s on c.clientid = s.clientid inner join AccountReceivable f on 
c.clientid=f.clientid where c.clientid = @clientid

Потрясающие. Однако теперь, когда мы меняем имя столбца или переименовываем / перемещаем таблицу, вы должны обновить код приложения. Таким образом, вместо этого мы делаем две вещи:
Создание клиентов, Продажи, Представления AccountReceivables (вы не использовали бы Select *, но я здесь демонстрирую)

Use MainDB
GO
Create view v_Clients as select * from Clients
Create view v_Sales as select * from Sales
Create view v_AccountReceivable as select * from AccountReceivable
Go

Затем мы также создали бы хранимую процедуру, spGetClientSalesAR

Create proc spGetClientSalesAR @clientID int
as
Select c.ClientName as ClientName, 
       c.ClientAddress as ClientAddress, 
       s.totalSales as TotalSales, 
       f.CreditBlance as CreditBalance 
from
v_Clients c join v_Sales s 
    on c.clientid = s.clientid 
inner join v_AccountReceivable f 
    on c.clientid=f.clientid 
where c.clientid = @clientid

И пусть ваше приложение называет это.

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

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

Create view v_Clients as select * from ServerX.DatabaseY.dbo.Clients
Create view v_Sales as select * from ServerQ.DatabaseP.dbo.Sales
Create view v_AccountReceivable as select * from ServerJ.DatabaseK.dbo.AccountReceivable

И ваше приложение никогда не узнает разницы (при условии, что между прочим будут быстрые каналы и хорошо поставленные данные).

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


TetonSig - спасибо за ответ. Я не смог вовремя вернуться к вопросу, чтобы назначить вам полную награду (я путешествовал), но я создал новую награду за этот вопрос и смогу вручить ее вам в течение 24 часов.
VirtuosiMedia

Вау, спасибо. Я ценю это. Было очень весело отвечать на вопрос.
TetonSig

5

Основным способом, с которым я столкнулся с несколькими серверами баз данных в веб-мире (поскольку вопрос помечен как PHP), являются настройки, в которых была одна база данных «master» (запись), а затем одна или несколько реплицированных баз данных «slave» (чтение) , Запись в базу данных выполняется для базы данных master. Содержимое этой базы данных реплицируется на подчиненные серверы практически в режиме реального времени. Запросы - особенно интенсивные отчеты - затем запускаются для одной из «ведомых» баз данных, чтобы перенести нагрузку на эти серверы. Имейте в виду, что эта конкретная установка лучше всего подходит для приложений, которые много читают, но не много пишут. Это ни в коем случае не единственный способ устроить вещи.


3

Как строятся соединения между двумя таблицами в нескольких базах данных? (Пример кода здесь будет полезен).

Они не. Базы данных NoSQL вообще не выполняют «объединения», и даже если бы вы могли выполнять SQL-соединение на серверах RDBMS, вы бы не захотели этого делать, если цените производительность (см. Ошибки распределенных вычислений ).

Существуют ли какие-либо специальные стратегии для отслеживания того, какие таблицы находятся в какой базе данных?

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

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

Базы данных NoSQL представляют собой сочетание решений для разделения. Иногда это «таблицы» (или чаще «коллекции»), которые разбиваются на части. В других случаях это «строки» (или «документы»). В некоторых случаях это на самом деле столбцы , как в базе данных, ориентированной на столбцы , такой как HBase. Это полностью зависит от технологии, которую вы используете. Единственное, что их объединяет, - это то, что сам движок отслеживает все это, поэтому все, что вам нужно сделать, это запросить документ или строку.

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

Нужно ли коду приложения знать, что одна или несколько баз данных распределены по нескольким серверам? Если нет, то на каком уровне фильтруются запросы?

Если это разные логические базы данных, да. Если они распределены только физически, то нет - при условии, что либо ваша конкретная база данных изначально поддерживает сегментирование, либо вы используете решение для балансировки нагрузки (для баз данных SQL). Также предположим, что все ваши операции не имеют состояния; если вы хотите горизонтальное масштабирование, вам придется отказаться от ACID.

Когда пора выходить за рамки настройки 1 базы данных / 1 сервера? Насколько часто это нужно делать?

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

Обратите внимание, что проблемы с производительностью в достойном продукте RDBMS (Oracle, SQL Server) чаще возникают из-за плохого дизайна, плохой индексации, плохих запросов, конкуренции за блокировку и т. Д .; эти продукты могут масштабироваться вертикально до смешной степени. Итак, еще раз, вы должны рассмотреть «выход за пределы настройки 1 базы данных / 1 сервера», когда вы абсолютно уверены, что ваши проблемы с производительностью связаны с аппаратными ограничениями, а не просто с подпроектом / реализацией.

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


+1 - я не особо задумывался о NoSQL, но это все равно полезно. Благодарю.
VirtuosiMedia

1

Существует три основных типа конфигураций репликации для баз данных:

  • Master-Slave
  • Мастер-Master
  • консенсус

Пример «ведущий-ведомый»: ведущий MySQL + ведомые MySQL, MongoDB

Пример Мастер-Мастер: CouchDB, Кассандра, Риак

Пример консенсуса: ScalienDB

...назвать несколько.

Они имеют разные характеристики. Конфигурации «ведущий-ведомый» позволяют подчиненным узлам догонять ведущий с их максимальной скоростью, в то же время очень быстро обслуживая запросы на чтение, в то время как ведущий сервер отвечает за целостность данных. Поскольку все записи отправляются ведущему устройству, конфликт блокировки никогда не возникает, потому что один относительно медленный модуль записи блокирует многие устройства чтения, но, с другой стороны, подчиненные серверы в конечном итоге становятся согласованными, и вы не получаете гарантий изоляции транзакций, которые бы вы имели от чтения только от мастера. (дальнейшее чтение; ACID против BASE, уровни изоляции транзакций, репликация базы данных, MVCC / изоляция: моментальный снимок, репликация транзакций)

Мастер-Мастер всегда разрешает записи, так что у вас есть несколько авторитетов в том, что правда. Это может или не может быть проблемой, в зависимости от того, что делает ваше приложение, но если вы пишете противоречивые данные, вы можете получить несколько результатов при следующем чтении этого ключа / строки / столбца, которые вам придется объединить с логикой приложения и сохранить обратно в базу данных. (дальнейшее чтение: теорема CAP, репликация CouchDB, репликация Riak, согласованное хеширование, Bitcask & StormDB, Quorum-w / MongoDB при разделении сети, стратегии разрешения слияний)

Основанные на консенсусе базы данных с репликацией между узлами, такими как Scalien, всегда будут согласованы при записи, но за счет обмена несколькими сообщениями перед подтверждением записи. Это не составляет большой проблемы, если у вас быстрый Ethernet и вам не нужно записывать на диск перед ACKing, который вам не понадобится, если минимум три сервера находятся на разных серверных стойках с отдельными блоками питания (один умирает, два других удостоверяются, что они сохранили на диске). (дальнейшее чтение; PAXOS, PAXOS COMMIT, двухфазная фиксация с распределенными транзакциями, трехфазная фиксация)

Дополнительное чтение: (книга: «Элементы распределенных вычислений», векторные часы, векторы версий, матричные векторы, логические часы, алгоритм хлебобулочных изделий, тактовые интервалы, акторы и реактивное программирование и реакторы, программная транзакционная память, транзакции, AKKA, Stact, ошибки распределенных вычислений, протоколы сплетен, анти-энтропийные расширения протокола Cassandra, распределенные хеш-таблицы, документы о слиянии данных в распределенной среде, архитектура ZooKeeper, презентация InfoQ на «асинхронном протоколе», архитектура HBase, бумага MapReduce, бумага Amazon Dynamo который запустил все NoSQL-вещи, очереди, кластеры высокой доступности rabbitmq)

Я надеюсь, что дал пищу для размышлений :). Вы можете подписаться на меня в твиттере @henrikfeldt, если вы тоже хотите твиты об этом.


1

Итак, вот еще одна точка зрения на масштабируемость.

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

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

Тем не менее, конкретный тип наслоения, который был нарушен, независимо от того, что когда-либо было, это «GUI», «Уровень бизнес-логики», а затем «Уровень доступа к данным». Я имею в виду, да, идея в принципе хороша, как коммунизм хорош в принципе, но на самом деле это не так.

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

По сути, идея заключается в том, что слои взаимозаменяемы; но это не так! Почему? Из-за всей связи колл-сайт.

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

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

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

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

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

Правильно, так с этим разглагольствования в сторону; какие еще способы есть?

Ну, есть ненавистная аббревиатура под названием «SOA», то есть сервис-ориентированная архитектура. Конечно, Томас Эрлс в мире , вы бы хотели, чтобы вы реализовали все свои уровни, но вместо этого с XML и SOAP.

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

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

Поскольку вы отделили фасады сервисов от реальных операций, которые вы хотите выполнить, теперь вы можете добавить несколько сервисов; На самом деле, так делает Netflix. Посмотрите на эти презентации: http://www.slideshare.net/adrianco/global-netflix-platform . http://www.slideshare.net/adrianco/global-netflix-platform . Они хороши!


0

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

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


Отдельная тема? Как это тогда соответствующий эталонный тест?
Хенрик,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.