Экспорт (0) Печать
Развернуть все

Проектирование стратегии масштабируемого секционирования для хранилища таблиц Azure

Обновлено: Август 2014 г.

Автор: https://msdn.microsoft.com/ru-ru/library/hh307529.aspx

Указанное изображение

Дополнительные сведения о консультировании по RBA.

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

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

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

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

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

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

Первичный ключ в любой таблице базы данных задает столбцы, которые уникально идентифицируют каждую строку. То же самое справедливо и для таблиц Azure. Первичный ключ для таблицы Azure представляет собой свойства PartitionKey и RowKey, которые формируют единый кластеризованный индекс в таблице. Каждое свойство PartitionKey и RowKey может хранить до 1 КБ строковых значений. Пустые строки также разрешены, но запрещены значения NULL. Кластеризованный индекс упорядочивается по PartitionKey в возрастающем порядке, а затем по RowKey также в возрастающем порядке. Этот порядок сортировки соблюдается во всех ответах на запросы. Во время операции сортировки используются лексические сравнения. Таким образом, строковое значение "111" будет отображаться перед строковым значением "2". В некоторых случаях может потребоваться числовой порядок. Чтобы выполнить сортировку в числовом порядке и по возрастанию, придется использовать дополненные нулями строки фиксированной длины. Если значение "2" из предыдущего примера задать как "002", то оно будет отображаться перед значением "111".

Секции представляют наборы сущностей с одинаковыми значениями PartitionKey. Секции всегда обслуживаются одним сервером секционирования, и каждый сервер секционирования может обслуживать одну или несколько секций. Сервер секционирования имеет ограничение скорости, касающееся числа сущностей из одной секции, которое он может обслуживать в течение некоторого времени. В частности, секция имеет целевой показатель масштабируемости в 500 сущностей в секунду. Эта пропускная способность может быть выше в период минимальной нагрузки на узел хранилища, но будет уменьшена, как только нагрузка сильно возрастет, или узел хранилища станет очень активным. Чтобы лучше проиллюстрировать концепцию секционирования, на следующем рисунке показана таблица, содержащая небольшое подмножество данных для регистрации событий в состязаниях по ходьбе. Она отражает концептуальное представление секционирования, в котором свойство PartitionKey содержит три разных значения, составленные из имени события и расстояния. В данном примере существует два сервера секционирования. Сервер A содержит регистрационные записи для полумарафона и десятикилометровой дистанции, а сервер B — только для полного марафона. Значения RowKey представлены для контекста; в данном примере они не имеют значения.

Указанное изображение

Поскольку секция всегда обслуживается с одного сервера секционирования, и каждый сервер секционирования может обслуживать одну или несколько секций, эффективность обслуживания сущностей зависит от работоспособности сервера. Серверы, которые сталкиваются с высоким трафиком для своих секций, могут быть не в состоянии поддерживать высокую пропускную способность. Например, на рисунке выше при наличии большого числа запросов "2011 New York City Marathon__Half" сервер A может стать слишком занятым. Чтобы повысить пропускную способность сервера, система хранения выполняет балансировку нагрузки этих секций на другие сервера. В результате трафик распределяется по нескольким другим серверам. Для оптимальной балансировки нагрузки трафика необходимо использовать большее число секций, поскольку это позволит службе таблиц Azure распределять секции на большее количество серверов секционирования.

Транзакция группы сущностей — это ряд операций сохранения, которые реализуются автоматически для сущностей с одинаковым значением PartitionKey. Если происходит сбой какой-либо операции сохранения в группе сущностей, то выполняется откат всех операций сохранения в этой группе. Транзакция группы сущностей включает не более 100 операций сохранения, и ее размер не может превышать 4 МБ. Транзакции группы сущностей представляют в таблицах Azure ограниченную форму семантики неразрывности, целостности, изоляционности, устойчивости (ACID), предоставляемой реляционными базами данных. Транзакции группы сущностей улучшают пропускную способность, поскольку сокращают число отдельных операций сохранения, которые должны передаваться в службу таблиц Azure. Кроме того, они выгодны экономически — транзакция группы сущностей оплачивается как одна операция сохранения, независимо от того, сколько операций сохранения она содержит. Так как все операции сохранения в транзакции группы сущностей затрагивают сущности с одним и тем же значением PartitionKey, желание использовать транзакции группы сущностей может влиять на выбор значения PartitionKey.

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

 

PartitionKey

RowKey

"0001"

-

"0002"

-

"0003"

-

"0004"

-

"0005"

-

"0006"

-

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

Присутствие в таблице секций диапазона может влиять на производительность операций вставки, если вставляются сущности с увеличивающимися или уменьшающимися значениями PartitionKey. Вставка сущностей с увеличивающимися значениями PartitionKey — это модель "Только присоединение", а вставка сущностей с уменьшающимися значениями — модель "Только добавление к началу". Не следует учитывать использование таких моделей, поскольку общая пропускная способность запросов на вставку будет ограничиваться одним сервером секционирования. Это объясняется тем, что при наличии секций диапазона первая и последняя секции (диапазона) будут содержать наименьшее и наибольшее значения PartitionKey соответственно. Следовательно, новая сущность с последовательно меньшим или большим значением PartitionKey будет вставляться в одну из этих граничных секций. На следующем рисунке показан возможный набор секций диапазона, исходя из предыдущего примера. Если вставляется ряд сущностей "0007", "0008" и "0009", то они будут назначены последней (оранжевой) секции.

Указанное изображение

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

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

Размер секций определяется числом сущностей, содержащихся в секции. Как упоминалось в разделе "Масштабируемость", увеличение числа секций означает улучшение балансировки нагрузки. Уровень детализации значения PartitionKey влияет на размер секций. На самом грубом уровне, когда в качестве PartitionKey используется одно значение, все сущности находятся в одной, очень большой секции. И наоборот, на самом тонком уровне детализации PartitionKey может содержать уникальные значения для каждой сущности. В результате каждая сущность будет находиться в отдельной секции. В следующей таблице показаны преимущества и недостатки разных уровней детализации.

 

Детализация PartitionKey

Размер секций

Преимущества

Недостатки

Одно значение

Небольшое количество сущностей

Пакетные транзакции возможны в любой сущности

Все сущности локальные и обслуживаются с одного узла хранилища

 

Одно значение

Большое количество сущностей

Транзакции группы сущностей могут быть возможны с любыми сущностями. Дополнительные сведения об ограничениях транзакций группы сущностей см. в статье http://msdn.microsoft.com/ru-ru/library/dd894038.aspx.

Масштабирование ограничено.

Пропускная способность ограничена производительностью одного сервера.

Несколько значений

Существует несколько секций

Размеры секций зависят от распределения сущностей

Пакетные транзакции возможны в некоторых сущностях

Возможно динамическое секционирование

Возможны запросы в одно предложение (нет маркеров продолжения)

Возможна балансировка нагрузки по нескольким серверам секционирования

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

Уникальные значения

Существует много небольших секций.

Таблица имеет высокую степень масштабируемости.

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

Для запросов, охватывающих диапазоны, может потребоваться заход на несколько серверов.

Пакетные транзакции невозможны.

Модели только присоединения или только добавления к началу могут влиять на пропускную способность операций вставки.

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

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

 

Тип запроса

Соответствие PartitionKey

Соответствие RowKey

Оценка производительности

Point

Точное

Точное

Лучший

Сканирование диапазона строк

Точное

Частично

Лучше при секциях меньшего размера

Плохая при очень больших секциях

Сканирование диапазона секций

Частично

Частично

Хорошая с небольшим числом затрагиваемых серверов секционирования

Ухудшается с ростом затрагиваемых серверов

Полное сканирование таблицы

Частичное, отсутствует

Частичное, отсутствует

Хуже при сканировании подмножества секций

Хуже при сканировании всех секций

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

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

http://<account>.windows.core.net/registrations(PartitionKey=”2011 New York City Marathon__Full”,RowKey=”1234__John__M__55”)

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

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

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

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

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

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

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

 

Если сущность…

Действие

Имеет одно ключевое свойство

Используйте его в качестве PartitionKey

Имеет два ключевых свойства

Используйте одно в качестве PartitionKey, а другое в качестве RowKey

Имеет более двух ключевых свойств

Используйте составной ключ из сцепленных значений

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

  • запрос по нагрудному номеру;

  • запрос по возрасту.

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

 

PartitionKey

RowKey

2011 New York City Marathon__Full

BIB:01234__John__M__55

2011 New York City Marathon__Full

AGE:055__1234__John__M

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

Таблицы Azure могут столкнуться с нагрузкой не только от запросов, но и от операций сохранения, таких как вставки, обновления и удаления. Необходимо проанализировать, какие типы операций сохранения будут выполняться в таблице, и как часто. Если эти операции будут выполняться редко, то их можно не учитывать. Однако если такие операции будут выполняться часто, например, если будет делаться много вставок в короткий период, то следует рассмотреть, как эти операции будут обслуживаться исходя из выбранных значений PartitionKey. Важный пример — модели только присоединения или только добавления к началу. Эти модели рассматривались выше, в разделе "Секции диапазона". Если применяется модель только присоединения или модель только добавления к началу, это означает, что при последовательных вставках для PartitionKey используются уникальные возрастающие или убывающие значения. При сочетании этой модели с часто выполняемыми операциями вставки таблица не сможет обслуживать операции вставки с высокой степенью масштабируемости. Масштабируемость таблицы пострадает потому, что Azure не сможет балансировать нагрузку запросов операций по другим серверам секционирования. Таким образом, в этом случае рекомендуется подумать об использовании произвольных значений, таких как значения GUID. Это позволит сохранять небольшой размер секций и в то же время поддерживать балансировку нагрузки при выполнении операций сохранения.

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

Для выполнения нагрузочного теста выполните следующие действия.

  1. Создайте тестовую таблицу.

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

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

  4. Исследуйте пропускную способность операций GET или PUT в таблице.

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

Балансировка нагрузки на уровне секций происходит, когда секция испытывает высокую нагрузку, что означает, что секция, а конкретнее сервер секционирования, работает за пределами своего целевого показателя масштабируемости. В хранилище Azure каждая секция имеет целевой показатель масштабируемости в 500 сущностей в секунду. Балансировка нагрузки также происходит на уровне распределенной файловой системы, или на уровне DFS. Балансировка нагрузки на уровне DFS имеет отношение к нагрузке операций ввода-вывода и выходит за рамки этой статьи. Балансировка нагрузки на уровне секции не происходит немедленно после превышения целевого показателя масштабируемости. Система ожидает несколько минут, прежде чем начать процесс балансировки нагрузки. Это гарантирует, что секция действительно начала испытывать высокую нагрузку. Нет необходимости инициировать секции с созданной нагрузкой, запускающей балансировку нагрузки, поскольку система будет выполнять эту задачу автоматически. Может оказаться, что если таблица была подвергнута определенной нагрузке, система будет балансировать секции на основе фактической нагрузки, что приведет к очень неравномерному распределению секций. Вместо подготовки секций рекомендуется подумать о создании кода, обрабатывающего ошибки типа "Время ожидания истекло" и "Сервер занят". Такие ошибки возвращаются, когда система выполняет балансировку нагрузки. При обработке этих ошибок с помощью стратегии повторов приложение сможет лучше справляться с пиковой нагрузкой. Стратегии повторов подробно рассматриваются в следующем разделе. При запуске балансировки нагрузки секция на несколько секунд становится автономной. В течение этого периода система переназначает секцию на другой сервер секционирования. Важно отметить, что серверы секционирования не сохраняют ваши данные. Они обслуживают сущности на уровне DFS. Поскольку на уровне секций данные не сохраняются, процесс перемещения секций на другие серверы выполняется быстро. Это существенно сокращает возможное время простоя вашего приложения.

Очень важно, чтобы приложение могло обрабатывать сбои операций сохранения, чтобы гарантированно исключить потерю каких-либо обновлений данных. Для обработки некоторых сбоев стратегия повторов не требуется. Например, если обновления возвращают ошибку "401 - Доступ запрещен", нет смысла повторять операцию, поскольку вряд ли состояние приложения изменится между повторами, чтобы устранить ошибку 401. Однако определенные ошибки, такие как "Сервер занят" или "Время ожидания истекло", относятся к функциям балансировки нагрузки Azure, обеспечивающим масштабируемость таблицы. Когда узлы хранилища, обслуживающие сущности, становятся слишком занятыми, Azure балансирует нагрузку, перемещая секции на другие узлы. В течение этого времени секция может стать недоступной, что и приводит к возникновению ошибки "Сервер занят" или "Время ожидания истекло". Со временем секция снова станет доступной, и можно будет возобновить обновления. Для таких ошибок подходит стратегия повторов. В большинстве случаев из логики повторов можно исключить ошибки уровня 400 и некоторые ошибки уровня 500, такие как "501 - Не реализовано" или "505 - Версия HTTP не поддерживается", и реализовать стратегию повторов для определенных ошибок уровня 500, таких как "Сервер занят" (503) и "Время ожидания истекло" (504).

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

  • Не повторять — попытки повтора не выполняются.

  • Фиксированная отсрочка — операция повторяется N раз с постоянным значением отсрочки.

  • Экспоненциальная отсрочка — операция повторяется N раз с экспоненциально растущим значением отсрочки.

Стратегия "Не повторять" — это простой (и половинчатый) способ обработки сбоев операций. Однако она не слишком полезна. Если не предпринимаются никакие попытки повтора, то существуют очевидные риски, что после неудачной операции данные не будут правильно сохранены. Следовательно, лучше использовать стратегию фиксированной отсрочки, которая предоставляет возможность повторения операций с одной и той же длительностью отсрочки. Однако эта стратегия не оптимальна для обработки высокомасштабируемых таблиц, поскольку если много потоков или процессов ожидают одно и то же время, могут возникать конфликты. Рекомендуемая стратегия повторов использует экспоненциальную отсрочку, когда каждая последующая попытка повтора ожидает дольше, чем предыдущая попытка. Она аналогична алгоритму исключения конфликтов, используемому в компьютерных сетях, таких как Ethernet. Экспоненциальная задержка с помощью случайного фактора обеспечивает дополнительное отклонение от итогового интервала. Затем значение задержки ограничивается минимальным и максимальным значением. Для вычисления следующего значения задержки с помощью экспоненциального алгоритма можно использовать следующую формулу:

y = Rand(0,8z, 1,2z)(2x-1

y = Min(zmin + y, zmax

Где:

z — задержка по умолчанию в миллисекундах;

zmin — минимальная задержка по умолчанию в миллисекундах;

zmax — максимальная задержка по умолчанию в миллисекундах;

x — число повторов;

y — значение задержки в миллисекундах.

Множители 0,8 и 1,2 используются в функции Rand, чтобы создать случайное отклонение от задержки по умолчанию в пределах ±20% от исходного значения. Диапазон ±20% подходит для большинства стратегий повторов и предотвращает последующие конфликты. Эту формулу можно реализовать с помощью следующего кода:

int retries = 1;
 
// Initialize variables with default values
var defaultBackoff = TimeSpan.FromSeconds(30);
var backoffMin = TimeSpan.FromSeconds(3);
var backoffMax = TimeSpan.FromSeconds(90);
            
var random = new Random();
 
double backoff = random.Next(
    (int)(0.8D * defaultBackoff.TotalMilliseconds), 
    (int)(1.2D * defaultBackoff.TotalMilliseconds));
backoff *= (Math.Pow(2, retries) - 1);
backoff = Math.Min(
    backoffMin.TotalMilliseconds + backoff, 
    backoffMax.TotalMilliseconds);


При разработке приложения с помощью управляемой библиотеки Azure можно использовать политики включенных повторов из клиентской библиотеки хранилища. Механизм повторов в этой библиотеке также позволяет расширить функциональность путем создания собственных политик повторов. Класс RetryPolicies в пространстве имен Microsoft.WindowsAzure.StorageClient предоставляет статические методы, возвращающие объект RetryPolicy. Объект RetryPolicy используется вместе с методом SaveChangesWithRetries в классе TableServiceContext. Политика по умолчанию, используемая объектом TableServiceContext, является экземпляром класса RetryExponential, построенным с помощью значений RetryPolicies.DefaultClientRetryCount и RetryPolicies.DefaultClientBackoff. Следующий код демонстрирует построение класса TableServiceContext с другой политикой RetryPolicy.

class MyTableServiceContext : TableServiceContext
{
    public MyTableServiceContext(string baseAddress, CloudStorageAccount account)
        : base(baseAddress, account)
    {
        int retryCount = 5; // Default is 3
        var backoff = TimeSpan.FromSeconds(45); // Default is 30 seconds

        RetryPolicy = RetryPolicies.RetryExponential(retryCount, backoff);
    }
    ...
}

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

Показ:
© 2015 Microsoft