View a markdown version of this page

Bloqueio positivo com número de versão - Amazon DynamoDB

Bloqueio positivo com número de versão

O bloqueio positivo é uma estratégia que detecta conflitos no momento da gravação, em vez de evitá-los. Cada item inclui um atributo de versão que aumenta a cada atualização. Ao atualizar um item, é necessário incluir uma expressão de condição que verifica se o número da versão corresponde ao valor que a aplicação leu pela última vez. Se outro processo modificou o item nesse meio tempo, a condição falhará e o DynamoDB exibirá uma ConditionalCheckFailedException.

Quando usar o bloqueio positivo

O bloqueio positivo é uma boa opção quando:

  • Vários usuários ou processos podem tentar atualizar o mesmo item, mas os conflitos são infrequentes.

  • O custo de tentar novamente uma gravação é baixo para a aplicação.

  • Você deseja evitar os custos indiretos e a complexidade do gerenciamento de bloqueios distribuídos.

Os exemplos comuns incluem atualizações de inventário de comércio eletrônico, plataformas de edição colaborativa e registros de transações financeiras.

Desvantagens

Custos indiretos de novas tentativas em alta contenção

Em ambientes de alta simultaneidade, a probabilidade de conflitos aumenta, podendo gerar mais tentativas e custos de gravação.

Complexidade de implementação

Adicionar controle de versão aos itens e lidar com verificações condicionais pode aumentar complexidade da lógica da aplicação. O AWS SDK para Java v2 Enhanced Client oferece suporte integrado por meio da anotação @DynamoDbVersionAttribute, que gerencia automaticamente os números de versão para você.

Padrão de design

Inclua um atributo de versão em cada item. Aqui está um design de esquema simples:

  • Chave de partição: um identificador exclusivo para cada item (por exemplo, ItemId).

  • Atributos:

    • ItemId: o identificador exclusivo do item.

    • Version: um número inteiro que representa o número da versão do item.

    • QuantityLeft: o estoque restante do item.

Quando um item é criado pela primeira vez, o atributo Version é definido como 1. Com cada atualização, o número da versão é incrementado em 1.

ItemID (chave de partição) Versão QuantityLeft
Bananas 1 10
Maçãs 1 5
Laranjas 1 7

Implementação

Para implementar o bloqueio positivo, siga estas etapas:

  1. Leia a versão atual do item.

    def get_item(item_id): response = table.get_item(Key={'ItemID': item_id}) return response['Item'] item = get_item('Bananas') current_version = item['Version']
  2. Atualize o item usando uma expressão de condição que verifica o número da versão.

    def update_item(item_id, qty_bought, current_version): try: response = table.update_item( Key={'ItemID': item_id}, UpdateExpression="SET QuantityLeft = QuantityLeft - :qty, Version = :new_v", ConditionExpression="Version = :expected_v", ExpressionAttributeValues={ ':qty': qty_bought, ':new_v': current_version + 1, ':expected_v': current_version }, ReturnValues="UPDATED_NEW" ) return response except ClientError as e: if e.response['Error']['Code'] == 'ConditionalCheckFailedException': print("Version conflict: another process updated this item.") raise
  3. Resolva os conflitos tentando novamente com uma nova leitura.

    Como cada nova tentativa requer uma leitura adicional, limite o número total de novas tentativas.

    def update_with_retry(item_id, qty_bought, max_retries=3): for attempt in range(max_retries): item = get_item(item_id) try: return update_item(item_id, qty_bought, item['Version']) except ClientError as e: if e.response['Error']['Code'] != 'ConditionalCheckFailedException': raise print(f"Retry {attempt + 1}/{max_retries}") raise Exception("Update failed after maximum retries.")

Em aplicações Java, o AWS SDK para Java v2 Enhanced Client oferece suporte integrado a bloqueio positivo por meio da anotação@DynamoDbVersionAttribute, que gerencia automaticamente os números de versão para você.

Para ter mais informações sobre expressões de condição, consulte Exemplo de expressão de condição do DynamoDB na CLI.