DynamoDB cuando la velocidad importa

Compartir

DynamoDB es una base de datos NoSQL propiedad de Amazon, es ofrecida dentro de los servicios de AWS, es su caballito de batalla en cuanto a velocidad en bases de datos se refiere, dado que está orientada a la alta disponibilidad, y su promesa de este servicio es ser una base de datos muy eficiente, sin embargo todos sabemos que AWS cobra por el consumo de sus servicios lo cual haremos una aproximación para calcular esto, y cómo sacar el provecho para asegurar su disponibilidad u otras razones.
Para entender un poco el nacimiento de DynamoDB, esta proviene de Dynamo, la diferencia es que Dynamo tiene una arquitectura leaderless replication, esto significa que todos replican sin un orquestador, el gran problema de esto se debe a problemas de versiones de datos porque a veces un dato fue versionado y se puede querer actualizar de nuevo perdiendo el control de las versiones que se van realizando, corrección que fue implementada en DynamoDB ya que su réplica se encuentra sincronizada, sabiendo cuando una tabla contiene la última actualización de la información. DynamoDB fue anunciado el 18 de Enero del 2012 por Werner Vogels el CTO de Amazon en el contexto de la evolución de SimpleDB otro servicio de base de dato NoSQL de alta disponibilidad propiedad de AWS.
Conceptos
Cuando hablamos de DynamoDB son mucho los conceptos que rodean a esta, y es importante aclararlos dado que nos ayuda a entender su capacidad y como se puede calcular el gasto que se llegaría a generar
Réplica automática la data se replica en múltiples zonas disponibles en una sola región, es importante entender que por región AWS tiene muchas zonas disponibles, y para mantener la alta disponibilidad de los datos esta va replicando la información en cada uno de estos espacios, asegurando la presencia de los datos.
Siempre con el sentido de proveer un servicio orientado a la velocidad es que los mecanismos encargados de leer y escribir en la base de datos son independientes, estos son conocidos como Write Capacity Unit y Read Capacity Unity:
- WCU Write Capacity Unit, es la encargada de escribir registros en la base de datos
- RCU Read Capacity Unit, es la encargada de leer los registros en la base de datos
La fisonomía de DynamoDB es muy parecida a las bases de datos relacionales en un inicio dado que esta contiene tablas e items, don estos son:
- Tabla conjunto de registro de datos guardados en DynamoDB
- Item Un registro almacenado en la tabla
Sin embargo las cosas comienzan a cambiar cuando es momento de crear sus tablas, si bien estas tienen una estructura llave valor, el comportamiento de esta llave valor es muy importante al momento de trabajar con DynamoDB, dado que la Primary key está compuesta por Partition key y en caso de ser requerida o necesitada se agrega una segunda componente de la llave denominada Sort key y los Attributes, donde se encuentra el cuerpo de la información, en términos más claro vemos lo siguiente:
- Partition Key llave principal por la cual se agruparán los datos, y determina cómo se particiona la data
- Sort Key llave de ordenamiento de los datos
- Primary Key composición entre la partition key y la sort key
- Attributes Corresponden al contenido de los datos estos pueden ser variados dado que DynamoDB no tiene una estructura de relacional

Para ser eficiente en el uso de recursos de DynamoDB es muy importante tener clara esta estructura y modelar los datos acorde a la Partition Key, esto se debe que se generan cluster de búsqueda y escritura en base a la agrupación de los datos. En los tipos de transacciones podemos encontrarnos con OLTP y OLAP, estas son:
- OLTP Online Transaction Process, DynamoDB es recomendado
- OLAP Online Analytical Process, DynamoDB no es recomendado
Para DynamoDB es recomendable solo considerarla cuando hablamos de OLTP, en consecuencia no es recomendable usar la base de datos para hacer analitica, esto se debe que al hacer analítica la necesidad de consultar por todos los registros es imperativo ya que se trabaja con la historia, y si hacemos esto se utilizarían de manera excesiva los recursos de DynamoDB, generando incluso costos excesivos.
Otros ejemplos y consideraciones al momento de armar una llave primaria es, imaginemos que se va a modelar un torneo de fútbol y se definió que la Partition Key sería la ciudad en donde se darán estos partidos, si este campeonato solo se da en 2 ciudades el número de Partition key será muy baja y los cluster serían muy pocos, lo cual terminaria en un mal manejo de la carga de los datos dado que el ideal es tener varios grupos pequeños y no dos grupos gigantes.
Un caso opuesto es que la Partition key sea un timestamp esto generará muchas llaves diferentes y creará espacios de almacenamientos muy esparcidos, en consecuencia al momento de realizar búsqueda no habrá una llave clara por la cual se realizará la búsqueda y se gastara mucho recurso en ésta.
Todo lo antes mencionado son problemas que pueden impactar en la sobrecarga de DynamoDB, donde ésta podría incluso llegar a tener problemas de acogotamiento (throttled), esto se genera por ejemplo, si tenemos 3 particiones, y 3 RCU, al momento de buscar cada RCU se encargará de buscar en cada una de esas particiones, y si una es muy larga o muy frecuentada se podría generar acogotamiento dado que una RCU estaría buscando en la partición todo el rato, o se demorara tanto en terminar de buscar que no sería equilibrada la carga.
La búsqueda en DynamoDB es realizada solo por la Primary Key o Partition Key, a pesar que igual se pueden hacer scan por los datos pero esto significa recorrer toda la base en busca del dato necesitado, y si la base es muy grande pasar por tanto registro requerirá un nivel de recursos muy grandes y posiblemente se genere el acogotamiento, es por esto que también existe el índice secundario que nos ayuda al manejo de los datos cuando necesitamos más llaves que estén asociada a la búsqueda, esta es una estructura de datos que contiene un subconjunto de atributos de una tabla, además de una clave alternativa para admitir las operaciones Query. Una tabla puede tener varios índices secundarios, lo que permite a las aplicaciones obtener acceso a distintos patrones de consulta, sin embargo existen dos tipos de índice secundario, donde cada uno de estos impacta directamente en la capacidad de búsqueda y almacenamiento, estos son:
- Global secondary index: índice con una clave de partición y una clave de ordenación que pueden diferir de las claves de la tabla base. Un índices secundario global se considera "global" porque las consultas del índice pueden abarcar todos los datos de la tabla base para todas las particiones. Un índices secundario global se almacena en su propio espacio de partición lejos de la tabla base y se escala por separado de la tabla base.
- Índice secundario local: índice que tiene la misma clave de partición que la tabla base, pero una clave de ordenación distinta. Un local secondary index es "local" en el sentido de que el ámbito de todas sus particiones corresponde a una partición de tabla base que tiene el mismo valor de clave de partición.
Si intentamos optimizar los recursos y no hacer tan costoso el uso de DynamoDB, es recomendable no tener un Global Secondary Index esto se debe a que es una tabla completamente diferente y ocupará más unidades de lectura o escritura para realizar sus operaciones.
Como el costo en general está dado por el consumo de recursos, es bueno poder estimar cuánto se va a necesitar en WCU y RCU para tener una estimación de las necesidades que tendremos y si tendremos un posible acogotamiento en DynamoDB, para esto es importante realizar el cálculo de las unidades de lectura y escritura, lo cual se realiza del siguiente modo:
Calculando Unidades de Escritura
- Redondea el tamaño del artículo hasta el incremento de 4KB más cercano, ejemplo, si el número es 13, se debe buscar el múltiplo más cercano a 4 pero hacia arriba, no deben haber sobras, porque si fuera 3 * 4 es 12 pero sobraría 1 por ende el valor seria 16, que equivale a 4 * 4.
- Divide el tamaño por 4kB, si consideramos que el artículo es de 13 entonces consideramos el 16 calculado anteriormente, entonces al dividir 16 por 4 es igual a 4.
- Multiplicar la respuesta por el número de elementos a leer, si fuesen 5 elementos a leer, se multiplica 5 con obtenido antes calculado 4, dando como resultado 20.
- SI la lectura es eventual luego divide la respuesta por 2, si la consistencia eventual está activada entonces el 20 anterior se divide en 2 quedando en 10.
Lecturas consistentes eventuales y fuertes. La consistencia eventual es el valor predeterminado y los datos generalmente se propagan en un segundo, esto significa que en casos de mucha concurrencia es posible que no siempre obtengas los datos actualizados. Si necesita lecturas muy consistentes, obviamente tendrá un impacto en el rendimiento, pero siempre recibirá resultados consistentes después de una escritura exitosa, aunque esto puede demorar un poco más y en caso de que falle la conexión de una de las fuentes se puede obtener un error 500.
Calculando unidades de escritura
- Cada unidad de escritura consta de 1KB. Entonces multiplique el número de artículos por tamaño en KB.
Ejemplos del cálculo de RCU y WCU
RCU P1 .-
- Pregunta: Lea 5 elementos a 10kB por segundo usando la consistencia eventual.
- Respuesta: 10kb redondeado hacia arriba al incremento más cercano múltiplo de 4kB = 12KB entonces 12KB / 4KB = 3 unidades de lectura por elemento, por lo tanto 3 * 5 elementos de lectura = 15, al tener consistencia eventual significa que dividimos entre 2 de modo que queda 15 / 2 = 7.5 y al redondear queda con 8 unidades de rendimiento de lectura.
RCU P2 .-
- Pregunta: Lea 5 artículos a 13KB por segundo usando una consistencia fuerte.
- Respuesta: 13KB redondeado hacia arriba al incremento más cercano de 4KB es 16KB, entonces 16KB / 4KB = 4 unidades de lectura por elemento 4 * 5 elementos de lectura = 20 se tiene consistencia fuerte, por lo que la respuesta es 20 unidades de rendimiento de lectura
WCU P1 .-
- Pregunta: Escriba 12 artículos de 100KB por segundo.
- Respuesta: Cada unidad de escritura consta de 1KB de datos, por lo que 12 * 100KB = 1200 unidades de escritura
Ya entendiendo un poco como funciona y la estructura de DynamoDB, para comenzar el AWS nos proporciona Plan gratuito el cual consiste en:
- 25 Gb de almacenamiento
- 25 unidades de escritura (WCU)
- 25 unidades de lectura (RCU)
- 1 GB de transferencia saliente de datos a los servicios de AWS
Con estos datos en consideración nos queda definir qué capacidad necesitamos dado que AWS nos da dos opciones, estas definen comportamiento en relación a las necesidades, las cuales son:
- Capacidad bajo demanda Esta aumenta o disminuye la capacidad dependiendo de la demanda que ésta se ve sometida
- Capacidad aprovisionada Si uno conoce el comportamiento de los clientes/usuarios es posible configurar la demanda que esperamos recibir y de este modo no necesitar que DynamoDB la configure por nosotros, este modo viene por defecto al momento de crear una tabla dado que si estamos conociendo DynamoDB

Como la idea es mantener los costos bajos, AWS nos provee de un mecanismo denominado TTL Time To Live, uno puede determinar cuando los registros ya son muy viejos y pasarlos a un s3 o borrarlos para que no usen espacio innecesario, y así poder darle otro uso a los datos sin necesidad de recargar la Base de Datos.
CRUD lambda
A continuación se deja un link a un CRUD básico de ejemplos con DynamoDB y Lambda: