Bloqueo positivo con el número de versión - Amazon DynamoDB

Bloqueo positivo con el número de versión

El bloqueo positivo es una estrategia que detecta los conflictos en el momento de la escritura en lugar de prevenirlos. Cada elemento incluye un atributo de versión que se incrementa con cada actualización. Al actualizar un elemento, se incluye una expresión de condición que comprueba si el número de versión coincide con el valor que leyó la aplicación por última vez. Si otro proceso ha modificado el elemento mientras tanto, la condición produce un error y DynamoDB devuelve una ConditionalCheckFailedException.

Cuándo utilizar el bloqueo positivo

El bloqueo positivo es una buena opción cuando:

  • Varios usuarios o procesos pueden actualizar el mismo elemento, pero los conflictos no son frecuentes.

  • Reintentar una escritura errónea no es costoso para la aplicación.

  • Es necesario evitar la sobrecarga y la complejidad de administrar bloqueos distribuidos.

Los ejemplos más comunes incluyen las actualizaciones del inventario del comercio electrónico, las plataformas de edición colaborativa y los registros de transacciones financieras.

Desventajas

Sobrecarga de reintentos en alta contención

En entornos de alta simultaneidad, aumenta la probabilidad de conflictos, lo que puede provocar un mayor número de reintentos y mayores costos de escritura.

Complejidad de la implementación

Agregar control de versiones a elementos y controlar condiciones agrega complejidad a la lógica de la aplicación. El cliente mejorado de AWS SDK para Java v2 ofrece soporte integrado a través de la anotación @DynamoDbVersionAttribute, que administra automáticamente los números de versión.

Diseño de patrón

Incluya un atributo de versión en cada elemento. A continuación, mostramos un esquema sencillo:

  • Clave de partición: un identificador único para cada elemento (por ejemplo, ItemId).

  • Atributos:

    • ItemId: el identificador único del elemento.

    • Version: un número entero que representa el número de versión del elemento.

    • QuantityLeft: el inventario restante del elemento.

Cuando se crea un elemento por primera vez, el atributo Version se establece en 1. Con cada actualización, el número de versión aumenta en uno.

ItemID (clave de partición) Versión QuantityLeft
Bananas 1 10
Manzanas 1 5
Naranjas 1 7

Implementación

Para implementar el bloqueo positivo, siga estos pasos:

  1. Lea la versión actual del elemento.

    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. Actualice el elemento mediante una expresión de condición que compruebe el número de versión.

    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. Controle los conflictos volviendo a intentarlo con una lectura nueva.

    Cada reintento requiere una lectura adicional, así que limite el número total de reintentos.

    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.")

Para aplicaciones de Java, el cliente mejorado de AWS SDK para Java v2 ofrece soporte de bloqueo positivo integrado a través de la anotación @DynamoDbVersionAttribute, que administra automáticamente los números de versión.

Para obtener más información sobre las expresiones de condición, consulte Ejemplo de la CLI de expresión de condición de DynamoDB.