Инструкции и рекомендации для надежных коллекций в Azure Service Fabric
В этом разделе приведены инструкции по использованию надежных коллекций и диспетчера надежных состояний. Цель этого руководства — помочь пользователям избежать распространенных ошибок.
Рекомендации по надежной коллекции
Инструкции составлены как простые рекомендации со словами Делайте, Постарайтесь, Избегайте и Не делайте в начале.
- Не изменяйте объекты пользовательского типа, возвращаемые операциями чтения (например,
TryPeekAsync
илиTryGetValueAsync
). Надежные коллекции, как и параллельные коллекции, возвращают ссылку на объект, а не его копию. - Обязательно создайте глубокую копию возвращенного объекта пользовательского типа, прежде чем изменять этот объект. Поскольку структуры и встроенные типы передаются по значению, вам необязательно создавать их глубокую копию, если они не содержат поля или свойства со ссылками, которые вы собираетесь изменить.
- Не используйте
TimeSpan.MaxValue
для времени ожидания. Время ожидания следует использовать для определения взаимоблокировок. - Не используйте транзакцию после того, как она была зафиксирована, прервана или удалена.
- Не используйте перечисление за пределами области транзакции, в которой оно было создано.
- Не создавайте транзакцию в операторе
using
другой транзакции, так как это может привести к взаимоблокировке. - Не создавайте надежное состояние с помощью
IReliableStateManager.GetOrAddAsync
и используйте надежное состояние в одной транзакции. Это приведет к исключению InvalidOperationException. - Убедитесь, что реализация
IComparable<TKey>
правильна. Система использует соответствующую зависимостьIComparable<TKey>
для слияния контрольных точек и строк. - Используете блокировку изменения при чтении элемента с целью обновить его, чтобы предотвратить взаимоблокировки определенного класса.
- Рекомендуем использовать менее 1000 надежных коллекций на раздел. Лучше использовать большее количество элементов в надежных коллекциях, чем большее количество надежных коллекций с меньшим количеством элементов.
- Постарайтесь поддерживать размер элементов (например, TKey + TValue для надежного словаря) до 80 КБ: чем меньше, тем лучше. Это позволит уменьшить объем использования кучи больших объектов, а также снизить требования к дискам и сетевым операциям ввода-вывода. Часто это также помогает уменьшить репликацию повторяющихся данных при обновлении только небольшой части значения. Распространенный способ добиться этого в надежном словаре — разбить строки на несколько строк.
- Возможно, вас заинтересует применение функций архивации и восстановления для аварийного восстановления.
- Избегайте совместного использования операций с одной сущностью и операций с несколькими сущностями (например,
GetCountAsync
,CreateEnumerableAsync
) в одной и той же транзакции ввиду различных уровней изоляции. - Обработайте исключение InvalidOperationException. Пользовательские транзакции могут быть прерваны системой по разным причинам. Например, если диспетчер надежных состояний изменяет свою роль с основной на какую-то другую, или когда транзакция с длительным временем выполнения блокирует усечение журнала транзакций. В таких случаях пользователь может получить исключение InvalidOperationException, указывающее на то, что его транзакция уже завершена. Если предположить, что завершение транзакции не было запрошено пользователем, то лучший способ обработки этого исключения — удалить транзакцию и проверить, не получен ли сигнал в виде токена отмены (или изменена роль реплики). И если нет, то создать новую транзакцию и повторить попытку.
- Не применяйте параллельные или параллельные операции в транзакции. В транзакции поддерживается только одна операция потока пользователя. В противном случае это приведет к утечке памяти и проблемам с блокировкой.
- Рассмотрите возможность удаления транзакции как можно скорее после завершения фиксации (особенно при использовании ConcurrentQueue).
- Не выполняйте блокирующий код внутри транзакции.
- Если строка используется в качестве ключа для надежного словаря, порядок сортировки использует сравнение строк по умолчанию CurrentCulture. Обратите внимание, что порядок сортировки CurrentCulture отличается от порядкового сравнения строк.
- Не удаляйте или отменяйте фиксацию транзакции. Это не поддерживается и может завершиться процессом узла.
- Убедитесь, что порядок операций разных словарей остается одинаковым для всех параллельных транзакций при чтении или написании нескольких словарей, чтобы избежать взаимоблокировки.
При этом нужно помнить о следующем:
- Время ожидания по умолчанию составляет 4 секунды для всех API надежных коллекций. Большинство пользователей должны использовать время ожидания по умолчанию.
- Во всех API надежных коллекций токеном отмены по умолчанию является
CancellationToken.None
. - Параметр типа ключа (TKey) для надежного словаря должен правильно реализовывать
GetHashCode()
иEquals()
. Ключи должны быть неизменяемыми. - Чтобы обеспечить высокую доступность надежных коллекций, в каждой службе необходимый и минимальный размер набора реплик должен быть равен как минимум 3.
- Операции чтения в базе данных-получателе могут считывать версии без кворума. Это означает, что версия данных, считываемая из отдельной базы данных-получателя, может быть ложно увеличена. Чтение из базы данных-источника всегда стабильно и не может вызывать ложное увеличение номера версии.
- Безопасность и конфиденциальность данных, хранимых приложением в надежной коллекции, зависит от вашего решения и средств, предоставляемых управлением хранилищем. Например, можно использовать шифрование дисков операционной системы для защиты неактивных данных.
- Перечисление
ReliableDictionary
использует отсортированную структуру данных, упорядоченную по ключу. Чтобы сделать перечисление эффективным, фиксации добавляются во временную хэш-таблицу и затем перемещаются в основную отсортированную структуру данных после контрольной точки. Операции добавления, обновления и удаления имеют лучшее время выполнения O(1) и худшее время выполнения O(log n) в случае проверки наличия ключа. Операции Get могут иметь сложность O(1) или O(log n) в зависимости от того, выполняется ли чтение из последней фиксации или из более старой фиксации.
Дополнительные рекомендации по переменным надежным коллекциям
При принятии решения о работе с непостоянными надежными коллекциями учитывайте следующее:
ReliableDictionary
поддерживает непостоянные коллекции.ReliableQueue
поддерживает непостоянные коллекции.ReliableConcurrentQueue
НЕ поддерживает непостоянные коллекции.- Хранимые службы НЕЛЬЗЯ сделать непостоянными. После изменения флага
HasPersistedState
наfalse
необходимо повторно создать всю службу с нуля. - Непостоянные службы НЕЛЬЗЯ сделать хранимыми. После изменения флага
HasPersistedState
наtrue
необходимо повторно создать всю службу с нуля. HasPersistedState
— это конфигурация уровня службы. Это означает, что ВСЕ коллекции будут либо хранимыми, либо временными. Использовать и непостоянные, и хранимые коллекции нельзя.- Потеря кворума в результатах непостоянной секции приводит к полной потере данных.
- Функции резервного копирования и восстановления НЕДОСТУПНЫ для непостоянных служб.
Следующие шаги
- Работа с надежными коллекциями
- Транзакции и блокировки
- Управление данными
- Другие
- Get started with Reliable Services (Начало работы с Reliable Services)
- Справочник разработчика по надежным коллекциям