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:
-
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'] -
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 -
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.