Transações e modos de bloqueio nas Coleções Fiáveis do Azure Service Fabric

Transação

Uma transação é uma sequência de operações executadas como uma única unidade lógica de trabalho. Apresenta as propriedades acid (atomicidade, consistência, isolamento, durabilidade) comuns das transações de bases de dados:

  • Atomicidade: uma transação tem de ser uma unidade atómica de trabalho. Por outras palavras, todas as modificações de dados são efetuadas ou nenhuma delas é efetuada.
  • Consistência: quando concluída, uma transação tem de deixar todos os dados num estado consistente. Todas as estruturas de dados internas têm de estar corretas no final da transação.
  • Isolamento: as modificações efetuadas por transações simultâneas têm de estar isoladas das modificações efetuadas por quaisquer outras transações simultâneas. O nível de isolamento utilizado para uma operação numa ITransaction é determinado pelo IReliableState que executa a operação.
  • Durabilidade: após a conclusão de uma transação, os respetivos efeitos estão permanentemente implementados no sistema. As modificações persistem mesmo em caso de falha do sistema.

Níveis de isolamento

O nível de isolamento define o grau em que a transação deve ser isolada das modificações efetuadas por outras transações. Existem dois níveis de isolamento suportados nas Coleções Fiáveis:

  • Leitura Repetível: especifica que as instruções não podem ler dados que foram modificados, mas que ainda não foram consolidados por outras transações e que nenhuma outra transação pode modificar os dados que foram lidos pela transação atual até a transação atual ser concluída.
  • Instantâneo: especifica que os dados lidos por qualquer instrução numa transação são a versão transacionalmente consistente dos dados que existiam no início da transação. A transação só pode reconhecer modificações de dados consolidadas antes do início da transação. As modificações de dados efetuadas por outras transações após o início da transação atual não são visíveis para as instruções executadas na transação atual. O efeito é como se as instruções numa transação obtêm um instantâneo dos dados consolidados tal como existiam no início da transação. Os instantâneos são consistentes em Coleções Fiáveis.

As Coleções Fiáveis escolhem automaticamente o nível de isolamento a utilizar para uma determinada operação de leitura, consoante a operação e a função da réplica no momento da criação da transação. Segue-se a tabela que ilustra as predefinições de nível de isolamento para operações de Dicionário Fiável e Fila.

Operação \ Função Primário Secundária
Leitura de Entidade Única Leitura Repetível Instantâneo
Enumeração, Contagem Instantâneo Instantâneo

Nota

Exemplos comuns para Operações de Entidade Única são IReliableDictionary.TryGetValueAsync, IReliableQueue.TryPeekAsync.

Tanto o Dicionário Fiável como a Fila Fiável suportam Ler As Suas Escritas. Por outras palavras, qualquer escrita numa transação será visível para uma leitura seguinte que pertença à mesma transação.

Bloqueios

Em Coleções Fiáveis, todas as transações implementam um rigoroso bloqueio de duas fases: uma transação não liberta os bloqueios que adquiriu até que a transação termine com uma abortação ou uma consolidação.

O Reliable Dictionary utiliza o bloqueio ao nível da linha para todas as operações de entidade única. A Fila Fiável troca a simultaneidade por uma propriedade FIFO transacional rigorosa. A Fila Fiável utiliza bloqueios ao nível da operação que permitem uma transação com TryPeekAsync e/ou TryDequeueAsync uma transação de EnqueueAsync cada vez. Tenha em atenção que, para preservar o FIFO, se uma TryPeekAsync ou TryDequeueAsync alguma vez observar que a Fila Fiável está vazia, também bloqueará EnqueueAsync.

As operações de escrita têm sempre bloqueios exclusivos. Para operações de leitura, o bloqueio depende de alguns fatores:

  • Qualquer operação de leitura efetuada com o isolamento de Instantâneos não tem bloqueio.
  • Por predefinição, qualquer operação de Leitura Repetível utiliza Bloqueios partilhados.
  • No entanto, para qualquer operação de leitura que suporte Leitura Repetível, o utilizador pode pedir um Bloqueio de atualização em vez do Bloqueio partilhado. Um Bloqueio de atualização é um bloqueio assimétrico utilizado para impedir uma forma comum de impasse que ocorre quando várias transações bloqueiam recursos para potenciais atualizações posteriormente.

A matriz de compatibilidade de bloqueio pode ser encontrada na seguinte tabela:

Pedido \ Concedido Nenhuma Partilhado Atualizar Exclusivo
Partilhado Sem conflito Sem conflito Conflito Conflito
Atualizar Sem conflito Sem conflito Conflito Conflito
Exclusivo Sem conflito Conflito Conflito Conflito

O argumento tempo limite nas APIs de Coleções Fiáveis é utilizado para deteção de impasse. Por exemplo, duas transações (T1 e T2) estão a tentar ler e atualizar K1. É possível que fiquem num impasse, uma vez que ambos acabam por ter o bloqueio Partilhado. Neste caso, uma ou ambas as operações excederão o tempo limite. Neste cenário, um Bloqueio de atualização pode impedir esse impasse.

Passos seguintes