DynamoDB en 360°, conceptos y buenas practicas

Por donde empezar a modelar datos No-SQL en DynamoDB. Entiende que es, como funciona y como adaptarlo a tus proyectos para sacarle provecho a AWS.

Gran parte de mi trabajo diario lo hago en la nube, mi plataforma favorita es Amazon Web Services y he experimentado con muchos recursos de la misma. Pero uno de los que más uso es DynamoDB.

Y me gustaría compartir contigo las consideraciones que creo se deben tener antes de ponerte manos a la obra.

Bien, para comenzar desde lo más elemental veamos que es dynamo y que nos ofrece.

DynamoDB es un motor NoSQL (no una base de datos) propiedad de Amazon que se enfoca en la performance, ya que por defecto replica la data de una tabla en mínimo 3 zonas de disponibilidad en la región en que se crea. De aquí viene la alta disponibilidad por la que es conocido. Si no estás familiarizado con los conceptos, regiones y zonas de disponibilidad, te recomiendo esta documentación: https://aws.amazon.com/es/about-aws/global-infrastructure

El tipo de replicación que usa dynamo y que viene a solventar el problema de la latencia de la actualización de los datos es conocida como replicacion leaderless . Para saber más de este concepto: https://distributed-computing-musings.com/2022/01/replication-introducing-leaderless-replication

Esto también se conoce como problema de inconsistencia de datos, en dynamo tenemos 2 conceptos para hablar de consistencia:

Eventually Consistent Reads.

Entre la escritura y la lectura de un dato existirá una leve latencia, por lo que consultar un dato recientemente escrito podría caer en una zona de disponibilidad que no tenía la última actualización. La documentación oficial no proporciona un tiempo exacto de delay, pero es casi imperceptible a menos que sea - por ejemplo - el score de un juego a tiempo real.

Strongly Consistent Reads

Esta consistencia es la que siempre responderá a las consultas con los últimos datos actualizados, sin excepción. Pero… según ciertas condiciones, y esa es su desventaja.

  • Una lectura fuertemente consistente puede no estar disponible si hay un retraso o una interrupción de la red. En este caso, DynamoDB puede devolver un error del servidor (HTTP 500).
  • Las lecturas fuertemente consistentes no son compatibles con los índices secundarios globales.
  • Las lecturas fuertemente consistentes utilizan más capacidad de rendimiento que las lecturas eventualmente consistentes. Este último dato nos lleva a nuestro siguiente concepto: la capacidad de lectura/escritura.
⚠️ DynamoDB utiliza Eventually Consistent Reads, a menos que se especifique lo contrario. Las operaciones de lectura(como GetItem, Query y Scan) proporcionan un parámetro ConsistentRead. Si establece este parámetro como verdadero, DynamoDB utiliza Strongly Consistent Reads.
Un error común es usar scan en vez de query para filtrar. Lo que se debe evitar siempre que se pueda, ya que scan debe recorrer toda la tabla, cuando tienes pocos elementos es irrelevante, pero ojo cuando estás trabajando con cientos de elementos.

Entre las preguntas que siempre te debes hacer antes de crear una tabla en dynamoDB están las siguientes:

  • ¿Cuál es el enfoque de los datos?
  • ¿Cuál es el tamaño promedio de los datos?
  • ¿Qué tan seguido tengo que leer los datos? ¿Necesito más capacidad, lectura o escritura? ¿Ambas por igual?
  • ¿Con qué velocidad quiero leer esos datos?
  • ¿Con qué velocidad quiero escribir datos?
  • ¿Qué clase de tabla Dynamo necesito? Esto se responde con facilidad, ya que son dos opciones, entonces ¿vamos a acceder a los datos con mucha o poca frecuencia?

Con respecto al tamaño de los datos y qué velocidad/capacidad de lectura y escritura necesitas. Debes entender como funcionan las unidades de capacidad y como elegirlas correctamente. Esto definirá que tan rápido podrás escribir y leer datos de una tabla.

Para definir la capacidad de lectura y escritura que necesitarás, debes definir primero que modo de capacidad de lectura/lectura necesitas.

El modo es el que define como se cobrara el rendimiento de lectura/escritura.

Los modos disponibles son dos:

  • On Demand: Significa que dynamo hará un escalado automático cada vez que fluctúe el tráfico de lectura y/o escritura de la tabla.
  • Usa este modo cuando no sepas a qué cargas de trabajo te enfrentas o cuando estas sean impredecibles.
  • Provisioned: Significa que tú especificaras las unidades de capacidad exactas, o que activando el Auto Scalingpuedes elegir un límite de Unidades de capacidad mínimas y máximas en la escritura y lectura.
  • Usa este modo cuando conozcas el tamaño de los datos y cuando sepas si es que estos varían y entre cuanto varían. También cuando tengas métricas sobre que tan seguido escribirás o leerás esos datos.
  • Si quieres usar este modo, pero no tienes clara las unidades de capacidad, puedes en primera instancia poner en modo On Demand o usar el Auto Scaling del modo provisioned y usar una métrica de medición en Cloudwatch para saber cuantas unidades de lectura y escritura necesitas. Ejemplo:


{
    "MyTableReadCapacityUnitsLimitAlarm": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "AlarmName": "myTable-ConsumedReadCapacity",
        "AlarmDescription": "Alarm when read capacity reaches 80% of my provisioned read capacity",
        "AlarmActions": [{ "Ref": "AlarmEmailNotificationSnsTopic" }],
        "Namespace": "AWS/DynamoDB",
        "MetricName": "ConsumedReadCapacityUnits",
        "Statistic": "Sum",
        "Period": "60",
        "Dimensions": [
          {
            "Name": "MyTableName",
            "Value": "arn:aws:dynamodb:{region}:{IdAccount}:table/MyTable"
          }
        ],
        "EvaluationPeriods": "1",
        "ComparisonOperator": "GreaterThanOrEqualToThreshold",
        "Threshold": "240",
        "Unit" : "Count"
      }
    }
}

Para mas casos y ejemplos: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/creating-alarms.html


Si no sabes implementar métricas, alarmas y monitoreo en Cloudwatch, dale un vistazo a este post: https://www.kranio.io/blog/metricas-y-alarmas-de-recursos-aws

Dato: Puedes cambiar el modo de capacidad de lectura/lectura cada 24hrs en un tabla.

Bien, pero hasta este punto no sabemos como se define una unidad de capacidad, así que, vamos a ello.

Para las tablas bajo demanda, las unidades de lectura se definen así:

  • Una solicitud de lectura strongly consistent de hasta 4 KB requiere una unidad de solicitud de lectura.
  • Una solicitud de lectura eventually consistent de hasta 4 KB requiere media unidad de solicitud de lectura.
  • Una solicitud de lectura transactional de hasta 4 KB requiere dos unidades de solicitud de lectura.

Para las tablas provisionales, las unidades de lectura se definen así:

RCU [unidad de capacidad de lectura]

  • 1 RCU es equivalente a una lectura de consistencia alta por segundo para un elemento de hasta 4 KB
  • 1 RCU es equivalente a dos lecturas eventualmente consistentes por segundo para un elemento de hasta 4 KB
  • 2 RCU es equivalente a una lectura transactional por segundo para elementos de hasta 4 KB

Por ejemplo: Imagina que tienes un archivo .xml de 8 KB

Si quieres una strongly consistent, necesitas dos RCU.

Si quieres una eventually consistent necesitas una RCU.

Si quieres una transactional necesitas 4 RCU.

WCU [unidad de capacidad de escritura]

  • 1 WCU es equivalente a una escritura por segundo para un elemento de hasta 1 KB
  • 2 WCU es equivalente a una escritura transactional por segundo para elementos de hasta 1 KB.
Por ejemplo: Tienes tu archivo .xml de 8 KB

Si quieres sostener solicitud de escritura estándar por segundo, necesitas 8 WCU.

Si quieres sostener una solicitud de escritura transactional, necesitas 32 WCU.

💡 Mas información sobre RCU y WCU:

https://n9.cl/ar38i

https://n9.cl/gr0fi

La configuración por defecto que proporciona dynamo para cuando no tienes claro nada de lo anterior es la siguiente:

Para pruebas esta muy bien, pero para proyectos reales, necesitas conocer tus datos y sus procesos, para llegar a la eficiencia y aproveches todas las posibilidades que dynamo te ofrece adaptándolo 100% a ti.

Anatomía básica de una tabla dynamo

Primary Key: Debe ser única y puede ser de dos tipos: partition key o composity primary key

Partition Key: Si la tabla sólo tiene una clave de partición, no puede haber dos elementos con el mismo valor de clave de partición.

Composity primary key: Es una combinación de clave de partición y clave de ordenación. Si la tabla tiene una clave primaria compuesta, dos elementos pueden tener el mismo valor de clave de partición. Sin embargo, esos elementos deben tener valores de clave de ordenación diferentes.

Sort Key: Debe ser única, conocida también como clave de ordenación.

Items: Cada tabla contiene cero o más elementos. Un elemento es un grupo de atributos que se puede identificar de forma única entre todos los demás elementos.

Attributes: Cada elemento está compuesto por uno o más atributos. Un atributo es un elemento de datos fundamental, algo que no necesita ser desglosado más.

DAX DynamoDB

Otro concepto que se debe tener en cuanta cuando se trabaja con datos enfocados a la consistencia y alta disponibilidad es el cacheo de los datos, si bien hay otro servicio aws llamado Elasticache con este objetivo, DynamoDB cuenta con su propio sub-servicio enfocado al caché, este es Dynamo accelerator (DAX). DAX se conforma por dos memorias caché ubicadas entre la tabla de datos dynamo y el cliente, uno es la caché de elementos y otra la caché de consultas.

El Flujo cuando se utiliza DAX es el siguiente:

Para una consulta [clave-valor] desde la aplicación del cliente se busca en la memoria Cache [DAX]. En caso de existir se devuelve el valor. Caso contrario se va a buscar a la tabla DynamoDB, se devuelve al cliente y se guarda en la memoria cache [DAX]. Si el cluster DAX tiene mas de un nodo el elemento se replica en todos los nodos para asegurar la consistencia.

Para el manejo de errores en dynamo

El manejo correcto de errores en cualquier desarrollo es siempre fundamental en la calidad de dicho desarrollo y dice mucho sobre el control que tiene el desarrollador sobre el código, o en este caso, sobre un recurso AWS.

Por suerte, aws dispone una buena documentación sobre los errores y su utilidad. Aun así veamos algunos puntos generales.

Si se esta implementando dynamo con SDK tienes respuestas http de 3 tipos:

  • 2xx para una operación exitosa.
  • 4xx para una operación que no fue exitosa. Este tipo de error tendrá 3 componentes
  • HttpCode
  • Nombre que le da dynamo a la excepción o problema que identificó.
  • Un mensaje de error que explica con mas claridad la causa del error.
  • Los errores 4xx disponibles son:
  • AccessDeniedException, ConditionalCheckFailedException, IncompleteSignatureException, ItemCollectionSizeLimitExceededException, LimitExceededException, MissingAuthenticationTokenException, ProvisionedThroughputExceeded, ProvisionedThroughputExceededException, RequestLimitExceeded, ResourceInUseException, ResourceNotFoundException, ThrottlingException, UnrecognizedClientException, ValidationException
  • 5xx para un problema propio de aws. También puede ser un error transitorio (de in disponibilidad operativa por ejemplo), que se puede resolver con un reintento. Los errores 5xx disponibles son:
  • Internal Server Error (HTTP 500)
  • Service Unavailable (HTTP 503)

Para hacer buen uso de estos errores se recomienda insertarlos en bloques try-catch.

💡 Puedes leer más sobre el manejo de errores aquí: https://n9.cl/ugvbo

💡 Dato: dynamo tiene un manejo especial para errores por el uso de DynamoDB Transactions, que consiste en realizar múltiples lecturas/escrituras en una sola solicitud. El error mas común son los conflictos, estos son:

  • Una solicitud PutItem, UpdateItem o DeleteItem de un elemento entra en conflicto con una solicitud TransactWriteItems en curso que incluye el mismo elemento.
  • Un elemento incluido en una solicitud TransactWriteItems forma parte de otra solicitud TransactWriteItems en curso.
  • Un elemento incluido en una solicitud TransactGetItems forma parte de otra solicitud TransactWriteItems, BatchWriteItem, PutItem, UpdateItem o DeleteItem en curso.

Para entender mejor que es DynamoDB Transactions: https://n9.cl/b9p0x

Bien ahora tienes conocimiento sobre que es dynamo, como funciona, y algunas consideraciones especiales para el buen manejo de tus datos. Recuerda seguir este consejo: analiza los datos antes de comenzar a modelar, entiende cual es su objetivo y concurrencia de lectura y escritura, con eso en mente tendrás mas control y por consiguiente mas eficiencia.

📌 Si tienes alguna duda o tu organización necesita apoyo para resolver proyectos de este tipo no dudes en contactarnos.

Jazmín Trujillo

September 16, 2024