Могу ли я получить элемент без блокировки от пункта надежного слова в сервисной структуре

Использование 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;

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

Другие вопросы по тегам