Поделиться через


Partitioning and horizontal scaling in Azure Cosmos DB (Секционирование и горизонтальное масштабирование в Azure Cosmos DB)

Область применения: Nosql Mongodb Кассандра Гремлин Таблица

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

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

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

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

Логические секции

Логическая секция состоит из набора элементов с одинаковым ключом секции. Например, в контейнере, в котором представлены данные о продуктах питания, все элементы содержат свойство foodGroup. Это свойство foodGroup можно использовать в качестве ключа секции для контейнера. Группы элементов с определенными значениями для foodGroup, например Beef Products, Baked Products и Sausages and Luncheon Meats, формируют отдельные логические секции.

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

Количество логических секций в контейнере не ограничено. Каждая логическая секция может хранить до 20 ГБ данных. Удачный выбор ключа секции подразумевает широкий диапазон возможных значений. Например, в контейнере, где все элементы содержат свойство foodGroup, размер данных в логической секции Beef Products может достигнуть 20 ГБ. Выбор ключа секции с широким диапазоном возможных значений гарантирует, что контейнер сможет масштабироваться.

Вы можете использовать оповещения Azure Monitor для отслеживания того, приближается ли размер логической секции к 20 ГБ.

Физические секции

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

Количество физических секций в контейнере зависит от следующих характеристик:

  • Подготовленная пропускная способность. (Каждая отдельная физическая секция может обеспечить пропускную способность до 10 000 единиц запросов в секунду.) Ограничение в 10 000 единиц запросов в секунду для физических секций подразумевает, что для логических секций также установлено ограничение в 10 000 единиц запросов в секунду, так как каждая логическая секция сопоставлена только с одной физической секцией.

  • Общее хранилище данных (каждая отдельная физическая секция может хранить до 50 ГБИТ/с данных).

Примечание.

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

Общее количество физических секций в контейнере не ограничено. По мере увеличения подготовленной пропускной способности или размера данных Azure Cosmos DB автоматически создает новые физические секции, разделяя существующие. Физические секции не влияют на доступность приложения. После разделения физической секции все данные из одной логической секции будут по-прежнему храниться в той же физической секции. При разделении физической секции просто создается новое сопоставление логических секций с физическими.

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

Например, рассмотрим контейнер с путем /foodGroup , указанным в качестве ключа секции. Контейнер может иметь любое количество физических секций, но в этом примере предполагается, что он имеет три. Одна физическая секция может содержать несколько ключей секций. Например, самая большая физическая секция может содержать три наиболее значимых логических секций Beef Products: , Vegetable and Vegetable Productsи Soups, Sauces, and Gravies.

Если вы назначаете пропускную способность 18 000 единиц запросов в секунду (ЕЗ/с), каждая из трех физических секций может использовать 1/3 из общей подготовленной пропускной способности. В пределах выбранной физической секции ключи логических секций Beef Products, Vegetable and Vegetable Products и Soups, Sauces, and Gravies в совокупности могут использовать 6000 единиц запросов в секунду от подготовленной пропускной способности. Так как подготовленная пропускная способность равномерно распределяется по физическим секциям контейнера, важно выбрать ключ секции, который равномерно распределяет потребление пропускной способности. Дополнительные сведения см. в разделе выбора правильного логического ключа секции.

Управление логическими секциями

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

Azure Cosmos DB распределяет логические секции между физическими путем секционирования на основе хэша. Azure Cosmos DB хэширует значение ключа секции для элемента. Хэшированные результаты определяют логическую секцию. Затем Azure Cosmos DB равномерно распределяет пространство для хэшей ключей секций по физическим секциям.

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

Наборы реплик

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

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

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

              Изображение, на котором продемонстрирован механизм секционирования в Azure Cosmos DB

Выбор ключа секции

Ключ секции содержит два компонента: путь и значение. Например, рассмотрим элемент { "userId" : "Andrew", "worksFor": "Microsoft" }. Если в качестве ключа секции выбрать userId, два компонента ключа раздела будут следующими:

  • Путь к ключу секции (например, "/userId"), Путь ключа секции принимает буквенно-цифровые символы и символы подчеркивания (_). Вы также можете использовать вложенные объекты также с помощью стандартной нотации пути (/).

  • Значение ключа секции (например, "Andrew"), которое может быть строкой или числовыми данными.

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

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

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

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

  • Должен содержать String только значения - или числа должны в идеале быть преобразованы в String, если есть любая вероятность того, что они находятся вне границ двойной точности чисел в соответствии с IEEE 754 binary64. В спецификации JSON указаны причины, по которым использование чисел за пределами этих границ в целом не рекомендуется из-за вероятных проблем со взаимодействием. Эти проблемы особенно важны для ключевого столбца секции, так как это неизменяемо и требует миграции данных позже.

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

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

  • Имеют значения, не превышающие 2048 байт, обычно или 101 байт, если большие ключи секции не включены. Дополнительные сведения см. в разделе "Большие ключи секции"

Если требуется многофакторная транзакция ACID в Azure Cosmos DB, необходимо использовать хранимые процедуры или триггеры. Все хранимые процедуры и триггеры на основе JavaScript ограничены одной логической секцией.

Примечание.

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

Типы ключей секций

Стратегия секционирования Когда используется Преимущества Недостатки
Обычный ключ секции (например, CustomerId, OrderId) — используется, если ключ секции имеет высокую кратность и соответствует шаблонам запросов (например, фильтрация по CustomerId).
— Подходит для рабочих нагрузок, где запросы в основном предназначены для данных одного клиента (например, получение всех заказов для клиента).
— Простое управление.
— Эффективные запросы, когда шаблон доступа соответствует ключу секции (например, запросу всех заказов с помощью CustomerId).
— предотвращает межсекционные запросы, если шаблоны доступа согласованы.
— Риск горячих секций, если некоторые значения (например, несколько клиентов с высоким трафиком) создают значительно больше данных, чем другие.
— может привести к ограничению на 20 ГБ на логическую секцию, если объем данных для определенного ключа быстро растет.
Искусственный ключ секции (например, CustomerId + OrderDate) — используется, если одно поле не имеет большого количества и соответствует шаблонам запросов.
— Хорошо подходит для рабочих нагрузок, в которых данные должны равномерно распределяться по физическим секциям (например, многие заказы, размещенные на одной дате).
— помогает равномерно распределять данные между секциями, уменьшая горячие секции (например, распространение заказов как CustomerId, так и OrderDate).
— распределяет записи по нескольким секциям, повышая пропускную способность.
— Запросы, которые фильтруют только по одному полю (например, CustomerId, только) могут привести к межсекционным запросам.
— Запросы между секциями могут привести к увеличению потребления ЕЗ (2-3 ЕЗ/с дополнительной платы за каждую физическую секцию, которая существует) и добавленную задержку.
Иерархический ключ секции (HPK) (например, CustomerId/OrderId, StoreId/ProductId) — Используйте, если требуется секционирование на нескольких уровнях для поддержки крупномасштабных наборов данных.
— Идеально подходит для фильтрации запросов на первом и втором уровнях иерархии.
— Помогает избежать ограничения на 20 ГБ путем создания нескольких уровней секционирования.
— Эффективное выполнение запросов на обоих иерархических уровнях (например, фильтрация сначала по CustomerID, а затем по OrderID).
— сводит к минимуму запросы между секциями для запросов, предназначенных для верхнего уровня (например, получение всех данных из определенного CustomerID).
— Требует тщательного планирования, чтобы убедиться, что ключ первого уровня имеет высокий кратность и включается в большинство запросов.
— более сложное управление, чем обычный ключ секции.
— Если запросы не соответствуют иерархии (например, фильтрация только по OrderID, если CustomerID является первым уровнем), производительность запросов может пострадать.

Ключи секций для контейнеров с высокой интенсивностью чтения

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

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

Однако если контейнер мал, вероятно, у вас недостаточно физических секций, чтобы беспокоиться о производительности запросов между секциями. Большинству таких контейнеров в Azure Cosmos DB требуется только одна или две физические секции.

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

  • В контейнере подготовлено более 30 000 единиц ЕЗ

  • Контейнер хранит более 100 ГБ данных

Использование идентификатора элемента в качестве ключа секции

Примечание.

Этот раздел в основном относится к API для NoSQL. Другие API, такие как API для Gremlin, не поддерживают уникальный идентификатор в качестве ключа секции.

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

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

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

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

При выборе идентификатора элемента в качестве ключа секции учитывайте перечисленные ниже моменты.

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