Вы можете разделить хранилище данных на несколько горизонтальных секций, которые называются сегментами. Это повышает масштабируемость при хранении больших объемов данных и обращении к ним.
Контекст и проблема
На хранилище данных, размещенное на обособленном сервере, могут распространятся следующие ограничения.
Дисковое пространство. Хранилища данных для крупных облачных приложений обычно содержат очень много информации, объем которой со временем увеличивается. Обычно объем дискового пространства на сервере ограничен. Хотя вы можете заменять существующие диски более емкими или добавлять дополнительные диски по мере накопления данных. Но рано или поздно система достигнет некоторого предела, сверх которого емкость хранилища на этом сервере увеличить будет невозможно.
Вычислительные ресурсы. Облачные приложения должны поддерживать большое число одновременно работающих пользователей, каждый из которых выполняет запросы на получение сведений из хранилища данных. Один сервер, на котором размещено хранилище данных, может не обеспечить необходимую вычислительную мощность для поддержки этой нагрузки, что приводит к расширенным времени отклика для пользователей и частым сбоям в качестве приложений, пытающихся хранить и извлекать время ожидания данных. Возможно, можно добавить процессоры памяти или обновления, но система достигнет предела, когда невозможно увеличить вычислительные ресурсы еще больше.
Пропускная способность сети. Производительность хранилища данных, запущенного на обособленном сервере, определяется еще и скоростью, с которой сервер может получать запросы и отправлять ответы. Когда объем сетевого трафика превышает пропускную способность сети, к которой подключен сервер, завершение некоторых запросов сбоями — реальная ситуация.
География. Иногда нужно, чтобы создаваемые пользователями данные хранились в том же регионе, где находятся сами пользователи. Это может быть связано с законодательными ограничениями, стандартами или требованиями к производительности и допустимой задержке при доступе к данным. Если при этом пользователи распределены по разным странам и регионам, вы не сможете хранить все данные приложения в одном хранилище данных.
Вертикальное масштабирование, например увеличение емкости дисков, вычислительной мощности, объема памяти или числа сетевых адаптеров, позволит обойти некоторые из этих ограничений, но, скорее всего, только временно. Коммерческое облачное приложение, поддерживающее большое число пользователей и оперирующее огромными объемами данных, должно масштабироваться практически без ограничений, поэтому вертикальное масштабирование не всегда будет наилучшим решением.
Решение
Вы можете разделить хранилище данных на горизонтальные секции (сегменты). Все сегменты имеют одинаковую схему данных, но хранят разные подмножества данных. Каждый сегмент сам по себе является хранилищем данных, которое может содержать данные для нескольких сущностей разных типов. Сегменты выполняются на сервере, который используется как узел хранения.
Такой подход связан со следующими преимуществами:
можно масштабировать систему, добавляя новые сегменты, запущенные на дополнительных узлах хранения;
система может работать на стандартном оборудовании, не требуя специализированных и дорогих компьютеров для каждого узла хранения;
можно минимизировать конфликты и повысить производительность, правильно распределяя рабочую нагрузку между сегментами;
сегменты, размещенные в облаке, могут физически располагаться рядом с пользователями, которые будут обращаться к данным.
Когда вы разделяете хранилище данных на сегменты, вам нужно определить, какие данные в какой сегмент будут помещены. Сегмент обычно содержит элементы, относящиеся к определенному диапазону по одному или нескольким атрибутам. Эти атрибуты формируют ключ сегмента (иногда его называют ключом секции). Ключ сегмента должен быть статическим. Он не должен основываться на данных, которые могут измениться.
Сегментирование определяет физическую структуру данных. Когда приложение сохраняет или извлекает данные, логика сегментирования определяет, к какому сегменту нужно обратиться. Эта логика сегментирования может быть реализована как в самом приложении, то есть в коде доступа к данным, так и в системе хранения данных, если хранилище прозрачно поддерживает сегментирование.
Решая вопросы физического расположения данных с использованием логики сегментирования, вы получаете возможность точно управлять распределением данных между сегментами. Если потребуется, вы сможете легко переносить данные между сегментами без необходимости изменять бизнес-логику приложения впоследствии (например, если изменится баланс распределения данных по сегментам). Единственный недостаток такой схемы — дополнительная нагрузка при доступе к данным, связанная с определением расположения каждого элемента данных при его получении.
Чтобы оптимально сбалансировать производительность и масштабируемость, очень важно правильно разделить данные в соответствии с тем, какие запросы выполняет приложение. Во многих случаях схемы сегментирования не смогут точно соответствовать требованиям каждого запроса. Например, в мультитенантной системе приложению может потребоваться получить данные клиента с помощью идентификатора клиента, но может потребоваться искать эти данные на основе другого атрибута, например имени или расположения клиента. В таких ситуациях желательно использовать такую стратегию сегментирования, при которой ключ сегмента соответствует наиболее часто выполняемым запросам.
Если нужно регулярно получать данные, используя сочетание значений некоторых атрибутов, вы можете определить составной ключ сегмента, связав нужные атрибуты. Можно использовать и другой подход — применить шаблон таблицы индексов, который позволит вам быстро находить данные по значениям атрибутов, не входящих в ключ сегмента.
Стратегии сегментирования
При выборе ключа сегмента и правил распределения данных по сегментам обычно используется одна из трех стратегий. Обратите внимание, что между сегментами и серверами, на которых они размещаются, не требуется однонационная связь— один сервер может размещать несколько сегментов. Давайте рассмотрим эти стратегии.
Стратегия поиска. В этом варианте логика сегментирования использует карту сопоставления по ключу сегмента и направляет запросы в тот сегмент, который содержит нужные данные. В мультитенантном приложении все данные клиента могут храниться вместе в сегменте с помощью идентификатора клиента в качестве ключа сегмента. Данные нескольких клиентов могут храниться в одном сегменте, но данные одного клиента не могут оказаться в нескольких сегментах. На рисунке показан вариант сегментирования данных по идентификаторам клиентов.
Сопоставление между значением ключа сегментов и физическим хранилищем, на котором существуют данные, могут быть основаны на физических сегментах, где каждое значение ключа сегментов сопоставляется с физической секцией. Кроме того, более гибким способом перебалансирования сегментов является виртуальная секционирование, где значения ключей сегментов сопоставляют с тем же числом виртуальных сегментов, которое, в свою очередь, сопоставляется с меньшим количеством физических секций. В этом подходе приложение находит данные с помощью значения ключа сегмента, которое относится к виртуальному сегменту, а система прозрачно сопоставляет виртуальные сегменты с физическими секциями. Сопоставление между виртуальным сегментом и физической секцией может измениться, не требуя изменения кода приложения для использования другого набора значений ключа сегментов.
Стратегия диапазонов. Эта стратегия группируют связанные элементы вместе в одном сегменте и упорядочивает их по ключу сегментов— ключи сегментов являются последовательными. Это полезно для приложений, которые часто получают наборы элементов из некоторого диапазона значений (запросы к данным возвращают набор элементов, для которых значения ключа сегмента попадают в заданный диапазон). Например если приложению нужно регулярно получать список всех заказов, размещенных в определенном месяце, эти данные можно получать быстрее, разместив заказы за каждый месяц в одном сегменте и упорядочив их по дате и времени. Если заказы окажутся в разных сегментах, их придется извлекать по отдельности, то есть выполнять большое количество точечных запросов (возвращающих один элемент данных). На следующем рисунке показана схема хранения последовательных наборов (диапазонов) данных в сегменте.
В этом примере используется составной ключ сегмента, наиболее значимым элементом которого является месяц заказа, затем которым следуют день и время заказа. При создании новых заказов и размещении их по сегментам данные естественным образом сортируются. Некоторые хранилища данных поддерживают ключи сегмента, состоящие из двух элементов — ключа секции, который определяет сегмент, и ключа строки, который однозначно определяет элемент в пределах сегмента. Обычно данные в сегменте хранятся в порядке значений ключа строки. Элементы, для которых применяются запросы по диапазонам значений и которые нужно хранить в одном сегменте, будут иметь одинаковые значения ключа секции и уникальные значения ключа строки.
Стратегия хэширования. Эта стратегия позволяет снизить вероятность возникновения высокоактивных сегментов (сегментов с непропорционально высокой нагрузкой). Данные в этом варианте распределяются между сегментами так, чтобы соблюдался баланс между размером каждого сегмента и средней нагрузкой, которая приходится на этот сегмент. Логика сегментирования вычисляет, в каком сегменте хранить каждый элемент данных, по значению хэш-индекса по одному или нескольким атрибутам данных. Функция хэширования должна быть выбрана так, чтобы равномерно распространять данные между сегментами. Возможно, для этого придется добавить в формулу вычисления некоторый случайный элемент. На следующем рисунке изображено сегментирование данных по хэшу идентификаторов клиента.
Чтобы понять преимущество хэш-стратегии по сравнению с другими стратегиями сегментирования, рассмотрим, как мультитенантное приложение, которое регистрирует новых клиентов последовательно, может назначить арендаторам сегменты в хранилище данных. Если использовать стратегию диапазонов, все данные о клиентах с идентификаторами от 1 до n сохраняются в сегменте A, с идентификаторами от n+1 до m — в сегменте B и т. д. Если предположить, что наибольшую активность проявляют недавно зарегистрированные клиенты, наибольшая нагрузка по работе с данными придется на небольшое число сегментов, что создаст высокоактивный сегмент. В этой же ситуации стратегия хэширования будет распределять клиентов по сегментам на основе хэша идентификатора. Это означает, что клиенты с последовательными идентификаторами, скорее всего, попадут в разные сегменты, что позволит равномерно распределить нагрузку. На рисунке выше показано такое поведение для клиентов с идентификаторами 55 и 56.
Далее описаны преимущества и особенности каждой из трех основных стратегий сегментирования.
Поиск. Обеспечивает максимальный контроль над настройкой и использованием сегментов. Используя виртуальные сегменты, можно устранить проблемы с балансировкой данных благодаря возможности добавлять новые физические секции для распределения рабочей нагрузки. Сопоставление виртуальных сегментов и физических секций, на которых они реализованы, можно изменять, не прибегая к программным методам, то есть не меняя код приложения, который сохраняет и извлекает данные по значению ключа сегмента. Поиск расположения сегмента может создавать дополнительную нагрузку.
Диапазон. Легко реализуется и хорошо работает с запросами по диапазонам, так как часто позволяет с помощью одной операции получить несколько элементов данных из одного сегмента. Эта стратегия упрощает процессы управления данными. Например, если включить в один сегмент пользователей из одного региона, можно запланировать обновления отдельно для каждого часового пояса на основе локальных особенностей использования нагрузки и запросов. Но эта стратегия не позволяет обеспечить оптимальную балансировку между сегментами. Перераспределение данных между сегментами будет сложным и не решит проблему неравномерной нагрузки, если основная часть нагрузки создается для данных с близкими значениями ключа сегмента.
Хэш. Позволяет распределять данные и нагрузку наиболее равномерно. Маршрутизация запросов выполняется прямо из приложения с использованием хэш-функции. Нет необходимости использовать карту сопоставления. Обратите внимание, что вычисление хэша может создать дополнительную нагрузку. Кроме того, это осложнит перераспределение нагрузки между сегментами.
Чаще всего в системах сегментирования используется один из описанных выше подходов, но вам нужно учитывать бизнес-требования и сценарии использования данных для своего приложения. Например, в мультитенантном приложении:
Вы можете сегментировать данные в зависимости от рабочей нагрузки. Вы можете распределить данные клиентов с очень нестабильным уровнем нагрузки в отдельные сегменты. Это может ускорить доступ к данным для других клиентов.
Вы можете сегментировать данные по расположению клиентов. Это позволит выполнять резервное копирование и обслуживание данных для клиентов из определенного географического региона в такие периоды, когда нагрузка в этом регионе будет минимальной. При этом данные клиентов из других регионов, где в это время продолжается рабочий день, останутся доступными.
Клиентам с высоким уровнем ценности могут быть назначены собственные частные, высокопроизводительные, легко загруженные сегменты, в то время как клиенты с более низкой стоимостью, возможно, будут делиться более плотно упакованными, занятыми сегментами.
Если отдельным клиентам требуется высокий уровень изоляции данных и конфиденциальности, их данные можно разместить на отдельном сервере.
Операции масштабирования и перемещения данных
Каждая стратегия сегментирования создает разные возможности и разные уровни сложности в контексте изменения масштаба, перемещения данных и поддержания состояния.
Стратегия поиска позволяет выполнять масштабирование и перемещение данных на уровне пользователей, и для этого не нужно отключать систему. Вам достаточно временно приостановить операции пользователей или некоторую их часть (это можно сделать в периоды низкой нагрузки), затем переместить данные в другую виртуальную секцию или другой физический сегмент, изменить карту сопоставлений и объявить недействительными или обновить все кэшированные данные. После этого можно возобновить работу пользователей. Операции такого типа часто можно выполнять централизованно. Стратегия поиска требует, чтобы состояние данных хорошо согласовывалось с кэшированием и реплицированием.
Стратегия диапазонов накладывает некоторые ограничения на операции масштабирования и перемещения данных. Обычно их нужно выполнять, отключив от сети хранилище данных или его часть, так как данные нужно делить и объединять во многих сегментах. Перемещение данных для балансирования сегментов не всегда позволит решить проблему неравномерной нагрузки, если основная часть нагрузки создается для данных с близкими значениями ключа сегмента или с идентификаторами из одного диапазона. Стратегия диапазонов также может включать действия по поддержанию состояния, чтобы диапазоны можно было сопоставить с физическими секциями.
Стратегия хэширования существенно осложняет операции масштабирования и перемещения данных, так как ключи секций — это хэш-индексы ключей сегментов или идентификаторов данных. Нужно определить новое расположение для каждого сегмента на основе результатов выполнения хэш-функции или изменить эту функцию для правильного сопоставления. Но зато стратегия хэширования не требует поддержания состояния.
Проблемы и рекомендации
При принятии решения о реализации этого шаблона необходимо учитывать следующие моменты.
Сегментирование можно использовать совместно с другими видами секционирования, такими как вертикальное или функциональное секционирование. Например, один сегмент может содержать сущности, которые секционированы по вертикали, а функциональное секционирование можно реализовать в виде нескольких сегментов. Дополнительные сведения о секционировании данных см. в этом руководстве.
Поддерживайте сбалансированное распределение нагрузки между сегментами, чтобы каждый из них обрабатывал сопоставимый объем операций ввода-вывода. По мере добавления и удаления данных нужно периодически перераспределять данные между сегментами, чтобы обеспечить равномерную нагрузку и избежать появления высокоактивных сегментов. Перераспределение может потребовать значительных ресурсов. Чтобы снизить потребность в перераспределении, учитывайте развитие системы при проектировании. Каждый сегмент должен иметь достаточно свободного места для обработки ожидаемого объема изменений. Также следует подготовить стратегии и планы для быстрого перераспределения данных, если это потребуется.
Используйте для ключа сегментов неизменяемые данные. Если для какого-либо элемента данных изменится значение ключа сегмента, возможно, его придется переместить в другой сегмент. Это увеличит объем работы при операциях обновления. Поэтому следует избегать сегментирования с использованием таких данных, которые могут измениться. Вместо этого выберите те атрибуты, которые остаются постоянными или формируют естественный ключ.
Обеспечьте уникальность значений для ключа сегмента. Например, в качестве ключа сегмента нежелательно использовать поля с автоприращением. В некоторых системах автоматически добавочные поля не могут быть согласованы между сегментами, возможно, в результате чего элементы в разных сегментах имеют один и тот же ключ сегментов.
Автоприращение значений в других полях, не входящих в ключ сегмента, также может вызвать проблемы. Например, если поля с автоприращением используются для создания уникальных идентификаторов, в разных сегментах двум элементам данных могут быть назначены одинаковые идентификаторы.
Не всегда будет возможность разработать такой ключ сегмента, который соответствует требованиям всех возможных запросов к данным. Выбирайте правила сегментирования так, чтобы они соответствовали самым часто выполняемым запросам, а при необходимости создайте дополнительные таблицы индексов для тех запросов, которые получают данные с использованием условий на основе других атрибутов, не входящих в ключ сегмента. Дополнительные сведения см. в статье Index Table pattern (Шаблон таблицы индексов).
Запросы, которые обращаются только к одному сегменту, выполняются более эффективно, чем те, которые получают данные из нескольких сегментов. Поэтому не следует реализовывать системы сегментирования, вынуждающие приложения выполнять большое число запросов к данным, распределенным между несколькими сегментами. Помните, что один сегмент может содержать данные для нескольких типов сущностей. Также можно попробовать денормализовать данные, чтобы хранить в одном сегменте связанные сущности, которые часто запрашиваются вместе (например, данные о клиентах и о размещенных ими заказах). Это позволит снизить число отдельных операций считывания, выполняемых приложением.
Если сущность, размещенная в одном сегменте, ссылается на сущность из другого сегмента, включите ключ сегмента для второй сущности в схему данных первой сущности. Это может повысить производительность запросов, которые обращаются к связанным данным из нескольких сегментов.
Если приложение должно выполнять запросы к данным из нескольких сегментов, получить такие данных можно с использованием параллельных задач. Например, это применимо для размноженных запросов, где данные из нескольких сегментов извлекаются параллельно и затем объединяются в единый результат. Но такой подход неизбежно усложняет логику доступа к данным.
Для многих приложений большое число мелких сегментов может оказаться более эффективной схемой, чем небольшое число больших сегментов. Это предоставляет больше возможностей для балансировки нагрузки. Это будет полезно и в том случае, если ожидается перенос сегментов из одного физического расположения в другое. Перемещение сегмента малого размера выполняется быстрее, чем перемещение большого сегмента.
Убедитесь, что каждый узел сегмента имеет достаточно ресурсов для масштабируемости по таким параметрам, как объем данных и пропускная способность. Дополнительные сведения см. в разделе "Проектирование секций для масштабируемости" в руководстве по секционированием данных.
Возможно, стоит реплицировать ссылочные данные во все сегменты. Если операции получения сегментированных данных в том же запросе обращаются к статической или медленно изменяющейся информации, добавьте эту информацию в сегмент. Тогда приложение сможет быстро получать все данные по этому запросу без дополнительного обращения к отдельному хранилищу данных.
Если изменятся ссылочные данные, хранимые в нескольких сегментах, система должна синхронизировать эти изменения между всеми сегментами. При такой синхронизации может возникать некоторая несогласованность. В таком случае приложение следует разрабатывать так, чтобы оно смогло справиться с ней.
Целостность и согласованность ссылочных данных между сегментами поддерживать трудно, поэтому старайтесь как можно меньше использовать операции, которые влияют на данные в нескольких сегментах. Если приложению необходимо изменять данные в нескольких сегментах, отдельно оцените необходимость полной согласованности данных. Обычно стандартный подход в облаке заключается в реализации окончательной согласованности. Данные в каждой секции обновляются отдельно, а логика приложения отвечает как за успешное завершение обновлений, так и за обработку несоответствий, которые могут возникнуть при запросах к данным на фоне выполнения операции по согласованию. Сведения о реализации согласованности в конечном счете см. в руководстве по обеспечению согласованности данных.
Настройка большого числа сегментов и управление ими могут представлять существенные сложности. Задачи мониторинга, резервного копирования, проверки согласованности, ведения журналов и аудита придется выполнять сразу для нескольких сегментов и серверов, возможно даже размещенных в нескольких расположениях. Эти задачи обычно можно реализовать с помощью скриптов или других решений по автоматизации, но не всегда удастся полностью устранить необходимость в дополнительных операциях по администрированию.
Сегменты могут быть привязаны к расположению, чтобы хранящиеся в них данные находились близко к тем экземплярам приложения, которые используют эти данные. Такой подход может значительно повысить производительность, но он также повысит требования к операциям, выполняемым для нескольких сегментов в разных расположениях.
Когда следует использовать этот шаблон
Используйте этот шаблон, если ожидаете, что требования к хранилищу данных могут превысить ресурсы, доступные для отдельного узла хранилища, или если хотите повысить производительность, избавляясь от конфликта ресурсов в хранилище данных.
Примечание.
Основная цель сегментирования — повысить производительность и масштабируемость системы. В качестве "побочного эффекта" вы можете также повысить доступность благодаря правильному распределению данных между сегментами. Сбой в одной секции не обязательно помешает приложению получать данные из других секций, а операции по обслуживанию или восстановлению данных в одной или нескольких секциях можно будет выполнять, не отключая для приложения доступ ко всем данным. Дополнительные сведения см. в руководстве по секционированию данных.
Проектирование рабочей нагрузки
Архитектор должен оценить, как шаблон сегментирования можно использовать в проектировании рабочей нагрузки для решения целей и принципов, описанных в основных принципах Платформы Azure Well-Architected Framework. Например:
Принцип | Как этот шаблон поддерживает цели основных компонентов |
---|---|
Решения по проектированию надежности помогают рабочей нагрузке стать устойчивой к сбоям и обеспечить восстановление до полнофункционального состояния после сбоя. | Так как данные или обработка изолированы к сегменту, сбой в одном сегменте остается изолированным для этого сегмента. - Секционирование данных RE:06 - RE:07 Самосохранение |
Оптимизация затрат ориентирована на поддержание и улучшение рентабельности инвестиций рабочей нагрузки. | Система, реализующая сегменты, часто получает преимущества от использования нескольких экземпляров менее дорогих вычислительных ресурсов или ресурсов хранилища, а не одного более дорогого ресурса. Во многих случаях эта конфигурация может сэкономить деньги. - Затраты на компоненты CO:07 |
Эффективность производительности помогает рабочей нагрузке эффективно соответствовать требованиям путем оптимизации масштабирования, данных, кода. | При использовании сегментирования в стратегии масштабирования данные или обработка изолированы к сегменту, поэтому она конкурирует за ресурсы только с другими запросами, направленными на этот сегмент. Вы также можете использовать сегментирование для оптимизации на основе географического региона. - Pe:05 Масштабирование и секционирование - Производительность данных PE:08 |
Как и любое решение по проектированию, рассмотрите любые компромиссы по целям других столпов, которые могут быть представлены с этим шаблоном.
Пример
Рассмотрим веб-сайт, который представляет собой расширяемую коллекцию информации о опубликованных книгах по всему миру. Количество возможных книг, каталогированных в этой рабочей нагрузке, и типичные шаблоны запросов и использования указывают на использование одной реляционной базы данных для хранения сведений о книге. Архитектор рабочей нагрузки решает сегментировать данные по нескольким экземплярам базы данных, используя статический номер международной стандартной книги (ISBN) для ключа сегментов. В частности, они используют контрольную цифру (0 – 10) ISBN, так как это дает 11 возможных логических сегментов, и данные будут достаточно сбалансированы по каждому сегменту. Для начала они решили объединить 11 логических сегментов в три физических базы данных сегментов. Они используют подход сегментирования подстановок и хранят сведения о сопоставлении ключей к серверу в базе данных карты сегментов.
Схема, показывающая службу приложение Azure с меткой "Веб-сайт каталога книги", которая подключена к нескольким экземплярам База данных SQL Azure и экземпляру службы поиска ИИ Azure. Одна из баз данных помечена как база данных ShardMap, и в ней есть пример таблицы, которая зеркально отражает часть таблицы сопоставления, которая также указана далее в этом документе. Также перечислены три экземпляра баз данных сегментов: bookdbshard0, bookdbshard1 и bookdbshard2. Каждый из баз данных содержит пример списка таблиц под ними. Все три примера идентичны, перечисляя таблицы "Книги" и "LibraryOfCongressCatalog" и индикатор дополнительных таблиц. Значок поиска ИИ Azure указывает, что он используется для фасетной навигации и поиска сайта. Управляемое удостоверение показано, связанное с службой приложение Azure.
Карта сегментов подстановки
База данных карты сегментов содержит следующую таблицу сопоставления сегментов и данные.
SELECT ShardKey, DatabaseServer
FROM BookDataShardMap
| ShardKey | DatabaseServer |
|----------|----------------|
| 0 | bookdbshard0 |
| 1 | bookdbshard0 |
| 2 | bookdbshard0 |
| 3 | bookdbshard1 |
| 4 | bookdbshard1 |
| 5 | bookdbshard1 |
| 6 | bookdbshard2 |
| 7 | bookdbshard2 |
| 8 | bookdbshard2 |
| 9 | bookdbshard0 |
| 10 | bookdbshard1 |
Пример кода веб-сайта — доступ к одному сегменту
Веб-сайт не знает о количестве баз данных физических сегментов (три в данном случае) или логике, которая сопоставляет ключ сегментов с экземпляром базы данных, но веб-сайт знает, что контрольная цифра ISBN книги должна считаться ключом сегментов. Веб-сайт имеет доступ только для чтения к базе данных карты сегментов и доступ на чтение и запись ко всем базам данных сегментов. В этом примере веб-сайт использует системное управляемое удостоверение службы приложение Azure, которое размещает веб-сайт для авторизации, чтобы сохранить секреты из строка подключения.
Веб-сайт настраивается со следующими строка подключения в файле, appsettings.json
например в этом примере или с помощью параметров приложения Служба приложений.
{
...
"ConnectionStrings": {
"ShardMapDb": "Data Source=tcp:<database-server-name>.database.windows.net,1433;Initial Catalog=ShardMap;Authentication=Active Directory Default;App=Book Site v1.5a",
"BookDbFragment": "Data Source=tcp:SHARD.database.windows.net,1433;Initial Catalog=Books;Authentication=Active Directory Default;App=Book Site v1.5a"
},
...
}
При наличии сведений о подключении к базе данных карты сегментов пример запроса обновления, выполняемого веб-сайтом в пуле сегментов рабочей нагрузки, будет выглядеть примерно так, как показано в следующем коде.
...
// All data for this book is stored in a shard based on the book's ISBN check digit,
// which is converted to an integer 0 - 10 (special value 'X' becomes 10).
int isbnCheckDigit = book.Isbn.CheckDigitAsInt;
// Establish a pooled connection to the database shard for this specific book.
using (SqlConnection sqlConn = await shardedDatabaseConnections.OpenShardConnectionForKeyAsync(key: isbnCheckDigit, cancellationToken))
{
// Update the book's Library of Congress catalog information
SqlCommand cmd = sqlConn.CreateCommand();
cmd.CommandText = @"UPDATE LibraryOfCongressCatalog
SET ControlNumber = @lccn,
...
Classification = @lcc
WHERE BookID = @bookId";
cmd.Parameters.AddWithValue("@lccn", book.LibraryOfCongress.Lccn);
...
cmd.Parameters.AddWithValue("@lcc", book.LibraryOfCongress.Lcc);
cmd.Parameters.AddWithValue("@bookId", book.Id);
await cmd.ExecuteNonQueryAsync(cancellationToken);
}
...
В приведенном выше примере кода, если book.Isbn
было 978-8-1130-1024-6, isbnCheckDigit
то должно быть 6. Обычно вызов OpenShardConnectionForKeyAsync(6)
будет реализован с помощью подхода в сторону кэша. Он запрашивает базу данных карты сегментов, определяемую строка подключения ShardMapDb
если она не содержит кэшированные сведения о сегменте для ключа сегментов 6. Либо из кэша приложения, либо из базы данных сегментов, значение bookdbshard2 занимает место SHARD
в BookDbFragment
строка подключения. Соединение с пулом устанавливается (повторно) для bookdbshard2.database.windows.net, открывается и возвращается в вызывающий код. Затем код обновляет существующую запись в этом экземпляре базы данных.
Пример кода веб-сайта — доступ к нескольким сегментам
В редких случаях прямой кросс-сегментный запрос требуется веб-сайтом, приложение выполняет параллельный запрос вентилятора во всех сегментах.
...
// Retrieve all shard keys
var shardKeys = shardedDatabaseConnections.GetAllShardKeys();
// Execute the query, in a fan-out style, against each shard in the shard list.
Parallel.ForEachAsync(shardKeys, async (shardKey, cancellationToken) =>
{
using (SqlConnection sqlConn = await shardedDatabaseConnections.OpenShardConnectionForKeyAsync(key: shardKey, cancellationToken))
{
SqlCommand cmd = sqlConn.CreateCommand();
cmd.CommandText = @"SELECT ...
FROM ...
WHERE ...";
SqlDataReader reader = await cmd.ExecuteReaderAsync(cancellationToken);
while (await reader.ReadAsync(cancellationToken))
{
// Read the results in to a thread-safe data structure.
}
reader.Close();
}
});
...
В качестве альтернативы меж сегментированным запросам в этой рабочей нагрузке может использоваться внешний индекс в службе "Поиск ИИ Azure", например для поиска сайтов или фасетной навигации.
Добавление экземпляров сегментов
Команда рабочей нагрузки знает, что если каталог данных или его параллельное использование значительно увеличивается более трех экземпляров базы данных, может потребоваться. Команда рабочей нагрузки не ожидает динамического добавления серверов базы данных и будет терпеть простой рабочей нагрузки, если новый сегмент должен быть подключен к сети. При создании нового экземпляра сегментов в сети требуется перемещение данных из существующих сегментов в новый сегмент вместе с обновлением в таблицу карты сегментов. Этот довольно статический подход позволяет рабочей нагрузке уверенно кэшировать сопоставление базы данных ключей сегментов в коде веб-сайта.
Логика ключа сегментов в этом примере имеет жесткий верхний предел в 11 физических сегментов. Если команда рабочей нагрузки выполняет тесты оценки нагрузки и оценивает, что в конечном итоге потребуется более 11 экземпляров баз данных, потребуется внести инвазивное изменение в логику ключа сегментов. Это изменение включает в себя тщательное планирование изменений кода и миграции данных в новую логику ключа.
Функциональные возможности пакета SDK
Вместо написания пользовательского кода для управления сегментами и маршрутизации запросов к База данных SQL Azure экземплярам оцените клиентскую библиотеку эластичной базы данных. Эта библиотека поддерживает управление картами сегментов, маршрутизацию запросов, зависящих от данных, и меж сегментные запросы в C# и Java.
Следующие шаги
При реализации этого шаблона следует принять во внимание следующие рекомендации:
- Data Consistency Primer (Руководство по обеспечению согласованности данных). Возможно, вам потребуется поддерживать согласованность данных, распределенных между разными сегментами. Здесь кратко описаны проблемы, связанные с поддержанием согласованности распределенных данных, и описываются преимущества и недостатки различных моделей согласованности.
- Data Partitioning Guidance (Руководство по секционированию данных). Сегментирование хранилища данных может привести к некоторым сопутствующим проблемам. Здесь описаны проблемы, связанные с секционированием хранилища данных в облаке, которое позволяет повысить масштабируемость, сократить число конфликтов и оптимизировать производительность.
Связанные ресурсы
При реализации этого шаблона могут быть также важны следующие шаблоны:
- Шаблон таблицы индексов. Иногда даже правильно выбранный ключ сегмента не позволяет выполнить все потребности запросов. Этот шаблон позволяет приложению быстро получать данные из хранилища большого объема благодаря использованию ключа, не совпадающего c ключом сегмента.
- Materialized View Pattern (Шаблон материализованного представления). Поддержать производительность некоторых запросов помогут материализованные представления, которые выполняют объединение и анализ данных. Это особенно полезно, если сводные данные основываются на информации, распределенной между несколькими сегментами. Здесь описано, как создать и заполнить такие представления.