Могу ли я получить элемент без блокировки от пункта надежного слова в сервисной структуре
Использование TryGetValueAsync для получения элемента из надежного словаря имеет либо блокировку по умолчанию, которая, как я полагаю, является общей блокировкой, либо блокировку записи, которая блокирует запись в другой транзакции. Есть ли способ получить элемент из надежного словаря без блокировки?
1 ответ
Согласно документации, Service Fabric автоматически управляет уровнями транзакций и ищет вас (это означает, что вы не можете их изменить).
Транзакции имеют два уровня изоляции:
- Повторяемое чтение: указывает, что операторы не могут читать данные, которые были изменены, но еще не зафиксированы другими транзакциями, и что никакие другие транзакции не могут изменять данные, которые были прочитаны текущей транзакцией, до тех пор, пока текущая транзакция не завершится.
- Снимок: указывает, что данные, считанные любым оператором в транзакции, являются согласованной с точки зрения транзакций версией данных, существовавших в начале транзакции. Транзакция может распознавать только те изменения данных, которые были зафиксированы до начала транзакции. Изменения данных, сделанные другими транзакциями после начала текущей транзакции, не видны операторам, выполняющимся в текущей транзакции. В результате операторы в транзакции получают моментальный снимок зафиксированных данных в том виде, в котором они существовали в начале транзакции. Снимки одинаковы для всех надежных коллекций.
В документации говорится, что все SER (чтение одного объекта) на первичной реплике всегда имеют уровень изоляции Repeatable Read (TryGetValueAsync
является операцией SER), поэтому нет способа изменить это для первичной реплики. В то же время для вторичной реплики все виды чтения всегда имеют уровень изоляции Snapshot.
Поэтому решение, которое я могу предложить, - это прочитать данные из вторичных реплик. Вот как можно получить адрес вторичной реплики, используя ServicePartitionResolver
учебный класс:
var partition = await ServicePartitionResolver.GetDefault().ResolveAsync(
tuple.serviceName,
new ServicePartitionKey(tuple.partitionName),
cancellationToken);
var address = partition.Endpoints
.Single(e => e.Role == ServiceEndpointRole.StatefulSecondary)?.Address;
Недостатком этого подхода является то, что вторичные данные реплики могут быть немного устаревшими из-за задержки репликации.