Jason
Jason

Reputation: 11

Can I get an item without lock from reliableDictionary in service fabric

Using TryGetValueAsync to get an item from reliable dictionary either has a default lock which I assume is shared lock or a write lock which will block the write in other transaction, is there a way to get an item from reliable dictionary without lock?

Upvotes: 1

Views: 329

Answers (1)

Oleg Karasik
Oleg Karasik

Reputation: 969

According to the documentation Service Fabric automatically managed transaction levels and looks for you (this basically mean you can't change them).

Transactions have two isolation levels:

  • Repeatable Read: Specifies that statements cannot read data that has been modified but not yet committed by other transactions and that no other transactions can modify data that has been read by the current transaction until the current transaction finishes.
  • Snapshot: Specifies that data read by any statement in a transaction is the transactionally consistent version of the data that existed at the start of the transaction. The transaction can recognize only data modifications that were committed before the start of the transaction. Data modifications made by other transactions after the start of the current transaction are not visible to statements executing in the current transaction. The effect is as if the statements in a transaction get a snapshot of the committed data as it existed at the start of the transaction. Snapshots are consistent across Reliable Collections.

The documentation states that all SER (Single-Entity Read) on primary replica are always Repeatable Read isolation level (TryGetValueAsync is SER operation) so there is no way to change this for primary replica. At the same time for secondary replica all kind of reads always have Snapshot isolation level.


So the solution I can propose is to read the data from secondary replicas. This is how address of secondary replica can be acquired using ServicePartitionResolver class:

var partition = await ServicePartitionResolver.GetDefault().ResolveAsync(
    tuple.serviceName,
    new ServicePartitionKey(tuple.partitionName),
    cancellationToken);

var address = partition.Endpoints
    .Single(e => e.Role == ServiceEndpointRole.StatefulSecondary)?.Address;

The downside of this approach is that secondary replica data can be slightly outdated because of the replication delay.

Upvotes: 1

Related Questions