Руководство по секционированию данных

хранилище BLOB-объектов Azure

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

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

Примечание

Термин секционирование в этом руководстве обозначает процесс физического разделения данных на отдельные хранилища. Не следует путать его с секционированием таблиц в SQL Server.

Зачем секционировать данные?

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

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

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

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

  • Сопоставление хранилища данных с шаблоном использования. Секционирование позволяет развернуть любую секцию в хранилище данных любого типа в зависимости от стоимости и встроенных функций, которые предоставляет хранилище данных. Например, большие объемы двоичных данных могут храниться в хранилище BLOB-объектов, а более структурированные данные — в базе данных документов. См. статью Choose the right data store (Выбор правильного хранилища данных).

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

Проектирование секций

Ниже представлены три распространенных стратегии секционирования данных:

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

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

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

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

Горизонтальное секционирование (сегментирование)

На рисунке 1 показано горизонтальное секционирование или сегментирование. В этом примере данные инвентаризации продуктов разделены на сегменты на основании ключа продукта. Каждый сегмент содержит данные для непрерывного диапазона ключей сегментов (A-G и H-Z) в алфавитном порядке. Сегментирование распределяет нагрузку между несколькими компьютерами, уменьшая вероятность возникновения конфликтов и повышая производительность.

Горизонтальное секционирование данных (сегментирование) на основании ключа секции

Рис. 1. Горизонтальное секционирование данных (сегментирование) на основании ключа секции

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

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

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

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

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

Дополнительные сведения о горизонтальном секционировании см. в статье Шаблон сегментирования.

Вертикальное секционирование

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

Вертикальное секционирование данных по шаблону использования

Рис. 2. Вертикальное секционирование данных по шаблону использования

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

Другие преимущества вертикального секционирования:

  • Можно разделить относительно редко меняющиеся данные (название товара, его описание и цена) и часто меняющиеся данные (объем товарных запасов и дата последнего заказа). Редко меняющиеся данные приложение может кэшировать в памяти.

  • Конфиденциальные данные могут храниться в отдельной секции с применением дополнительных средств защиты.

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

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

Функциональное секционирование

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

Функциональное секционирование данных по связанному контексту или дочернему домену

Рис. 3. Функциональное секционирование данных по связанному контексту или дочернему домену

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

Проектирование секций для масштабируемости

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

При создании секций для масштабируемости выполните приведенные далее действия.

  1. Проанализируйте приложение, чтобы понять шаблоны доступа к данным, такие как размер результирующего набора, возвращаемого каждым запросом, частота доступа, встречающиеся задержки и требования к вычислительной обработке на стороне сервера. Во многих случаях несколько основных сущностей потребуют большую часть вычислительных ресурсов.
  2. На основе анализа определите текущие и будущие целевые показатели масштабируемости, такие как размер данных и рабочая нагрузка. Затем распределите данные по секциям в соответствии с целевыми показателями масштабируемости. При горизонтальном секционирования важно правильно выбрать ключ сегмента, чтобы обеспечить равномерное распределение. Дополнительные сведения см. в статье Шаблон сегментирования.
  3. Убедитесь в том, что каждой секции предоставлено достаточно ресурсов для выполнения требований масштабируемости в контексте объема данных и пропускной способности. В зависимости от хранилища данных могут существовать ограничения на объем хранения, вычислительную мощность или пропускную способность секции. Если требования, скорее всего, превысят эти ограничения, может потребоваться уточнить стратегию секционирования или дополнительно разделить данные, возможно, объединив две или более стратегий.
  4. Понаблюдайте за системой, чтобы убедиться, что данные распределяются ожидаемым образом и секции справляются со своей нагрузкой. Реальное использование не всегда соответствует аналитическим прогнозам. В таком случае можно повторно сбалансировать секции или изменить некоторые компоненты системы, чтобы добиться необходимого баланса.

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

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

Проектирование секций для повышения производительности запросов

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

При создании секций для производительности запросов выполните приведенные далее действия.

  1. Изучите требования и производительность приложения.

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

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

  4. Для повышения производительности рекомендуется выполнять параллельные запросы к секциям.

Проектирование секций для увеличения доступности

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

Учитывайте следующие факторы, влияющие на доступность:

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

  • Критически важные данные можно хранить в высокодоступных секциях с соответствующим планом резервного копирования.

  • Внедрите отдельные процедуры управления и мониторинга для различных наборов данных.

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

Как можно управлять отдельными секциями. Проектирование секций с поддержкой независимых управления и обслуживания обеспечивает ряд преимуществ. Пример:

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

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

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

Рекомендации по проектированию приложений

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Учитывайте следующие факторы, влияющие на оперативное управление.

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

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

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

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

Балансировка секций

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

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

  1. Определение новой стратегии секционирования.

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

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

Автономная миграция

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

  1. Отключите доступ к секции.
  2. Разделите или объедините секции и переместите данные в новые секции.
  3. проверить данные;
  4. Включите доступ к новым секциям.
  5. Удалите старую секцию.

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

Миграция по сети

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

Дальнейшие действия

Следующие шаблоны проектирования могут оказаться полезными для вашего сценария:

  • Шаблон сегментирования описывает некоторые распространенные стратегии сегментирования данных.

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

  • Шаблон материализованного представления описывает, как создавать предварительно заполненные представления, которые отображают итоговые данные для поддержки операций быстрых запросов. Этот подход можно использовать в секционированном хранилище данных, если секции, содержащие итоговые данные, распределены по нескольким сайтам.