El teorema CAP en base de datos

Éste post me parece muy importante para poder entender como funcionan y hacer grandes sistemas pensados para escalar, sea por tráfico, por multi-sitio, multi-país, y más… todos estos sistemas distribuidos presentan la misma particularidad, y en el año 2000 un señor llamado Eric Brewer, pudo definir tres importantes propiedades y desarrollo un teorema. El se dio cuenta que mientras más aplicaciones basadas en la WEB existan, menos debemos preocuparnos por la consistencia de los datos, si queremos alta disponibilidad de nuestras aplicaciones entonces no podemos garantizar la consistencia de los datos.

El teorema CAP, también llamado formalmente Teorema de Brewer, dice que un sistema de datos distribuido pude asegurar dos de estas tres propiedades: Consistencia, Disponibilidad y Tolerancia al particionado. Bien, que significa cada una:

  • La consistencia (Consistency), Todos los nodos deben ver los mismos datos al mismo tiempo, esto quiere decir que; cualquier cambios en los datos se debe aplicar en todos los nodos, y cuando se recupere el dato tiene que ser el mismo en todos los nodos. Esto se le llama consistencia atómica, y se consigue replicando la información en todos los nodos.
  • La disponibilidad (Availability), Cada petición en un nodo debe recibir y garantizar una confirmación si ha sido resuelta satisfactoriamente. En pocas palabras, se debe leer y escribir en todos los nodos.
  • La tolerancia al particionado (Partition Tolerance), El sistema debe funcionar a pesar de que haya sido dividido por un fallo de comunicación, garantizando la disponibilidad a pesar que un nodo se separe del grupo sin importar la causa.

CAPTheorem

El teorema solo nos puede garantizar las siguientes combinaciones:

  • CP (Consistency & Partition): El sistema aplicara los cambios de forma forma consistente y aunque se pierda la comunicación entre nodos ocacionando el particionado, no se asegura que haya disponibilidad.
  • AP (Availability & Partition): El sistema siempre estará disponible a las peticiones aunque se pierda la comunicación entre los nodos ocacionando el particionado, y en consecuencia por la perdida de comunicación existirá inconsistencia porque no todos los nodos serán iguales.
  • CA (Consistency & Availability): El sistema siempre estará disponible respondiendo las peticiones y los datos procesados serán consistentes. En este caso no se puede permitir el particionado.

La correcta decisión de que combinación necesitamos depende de nuestras necesidades de negocio. Nunca olvide que lo más importante en una base de datos relacional es la Consistencia. Conociendo el teorema CAP, nos puede ayudar aún más para saber que Sistemas de Base de Datos debemos escoger, si un SQL o un NoSQL. Si queremos profundizar más en el tema, recomiendo este post.

Bloqueos en MySQL

El bloqueo es la esencia de cualquier manejador de bases de datos relacional (RDBMS), para el caso de MySQL es importante destacar que el engine InnoDB lo gestiona de forma óptima, hasta la fecha no hay otro que lo haga mejor.

No podemos confundir bloqueos con niveles de aislamiento, ya que el bloqueo se hace a nivel de registros usando una instrucción específica, mientras el nivel de aislamiento es el comportamiento por defecto para cualquier otra instrucción normal que manipule los registros.

Los bloqueos existen para poder garantizar el ACID, su correcta implementación permite que halla concurrencia, de lo contrario se puede presentar la contención y es fatal.

Los bloqueos los podemos dividir en dos grandes grupos; está el bloqueo pesimista y el bloqueo optimista, vamos a entender cada uno:

  • Pesimista: Es aquel que se apodera del recurso (row/tabla) y no lo libera hasta que se haya modificado. Generalmente se hace con instrucciones propias del RDBMS. Para el caso de MySQL tenemos dos instrucciones; el SELECT … FOR UPDATE y el SELECT … LOCK IN SHARE MODE y no hablar de LOCK TABLE. Éste tipo de bloqueo produce Deadlock sin importar la forma como lo controlemos, al final estamos bloqueando un recurso que usa una conexión especifica, tiene un timeout, y otros procesos que esperan por el, esto puede generar una contención, problemas de atomicidad, y muchas más situaciones lamentables.
  • Optimista: Es la mejor forma de bloquear un recurso fomentando la concurrencia, no existe instrucción SQL que añada ésta funcionalidad, más bien usamos las instrucciones DML existentes, y se basa en la lógica del MVCC. Consiste en añadir una columna para versionar el registro y evitar que el último estado sea modificado. Por ejemplo: cuando una sesión quiere modificar un registro, ésta lee y hace UPDATE con la última versión conocida de dicho registro, si hay otra transacción que se adelanta para hacer el mismo UPDATE, la versión cambia, y el UPDATE será obsoleto.

Para la mayoría de las aplicaciones WEB, se debe utilizar el bloqueo optimista, como podemos ver, no es más que una implementación de una columna que versiona el registro y la combinación simple de un SELECT y un UPDATE, de esta forma evitamos los Deadlock, la contención, y muchos otros problemas. Los ORM, como por ejemplo Hibernate o ActiveRecord tienen ésta funcionalidad implementada, nos quitan una capa más de detalle y no será necesario modificar el modelo y las consultas.

¿Por qué no usar CloudFormation para Bases de Datos?

Dedique varias semanas en investigar como implementar CloudFormation de Amazon para montar un entorno de pruebas de Percona XtraDB Cluster con cuatro nodos, dos HAProxy, un servidor con Nagios, y una VIP, adicionalmente usando Puppet, la idea que me atrajo de usar CloudFormation fue la practicidad de definir toda una infraestructura de maquinas virtuales usando un JSON como template, el tener un formulario para definir variables, y luego tener la ventaja de poder crear y destruir cualquier cantidad de veces el cluster de forma automatizada.

Al final me di cuenta que no es seguro usar CloudFormation por varios motivos:

  • CloudFormation se asegura de mantener toda la infraestructura al 100% como está definida en el JSON. Si no hay algo que no encaja, crea una nueva maquina y destruye la anterior, al tener una Base de Datos con datos de producción los podemos perder muy fácilmente. Esto me paso al cambiar la versión de la AMI, note como se creaban nuevas maquinas, y luego cuando estaban listas, fueron remplazadas por las viejas y se perdieron todos los datos.
  • Se tendría que parametrizar mucho para reducir las probabilidades de destruir una maquina de forma accidentada. Esto le añade más complejidad en el flujo de trabajo y deja de ser intuitivo para cualquiera.
  • Contemplar todos los casos de administración de cada uno de los nodos de un cluster es complejo, por ejemplo, debemos contemplar la ampliación del disco sin perder los datos, cambiar el tipo de instancia, y cambiar las políticas de seguridad. Quien sabe que más puede pasar.

Poder superar todas las desventajas mencionadas requiere muchas horas de investigación y pruebas hasta lograr dominar todo, puede que nos demos cuenta que faltan más reglas por parte del CloudFormation, pienso que esto no fue echo para Bases de Datos, sino para servidores de API y WEB, donde los grandes volúmenes de datos no son un problema.

También pienso que usar CloudFormation en un caso de Bases de Datos está bastante bien para hacer una demo, o crear entornos para un sandbox por ejemplo, pero para producción lo veo muy peligroso.

Mi recomendación es irnos por lo clásico, crear tus propios scrips que hacen llamadas a la API de Amazon, así creas toda la infraestructura, defines tú el flujo de trabajo, y llevas el control, si yo habría echo así desde un principio, habría ahorrado mucho tiempo. De todo esto se obtiene una lección aprendida, y aquí la comparto.

Origen de la palabra NoSQL

Es curioso como se desencadena toda una revolución por un simple hashtag. Aquí les dejo una breve historia de su verdadero origen:

Johan Oskarsson organizó un evento en Junio de 2009 en San Francisco, la intención era discutir las nuevas tecnologías en el mundo IT sobre el almacenamiento y procesamiento de datos. La principal razón del evento fueron los nuevos productos como BigTable y Dynamo. Para el evento era necesario encontrar una palabra clave para ser usada en un hashtag de Twitter, término siendo NoSQL y fue sugerido por Eric Evans de RackSpace. El término fue planeado para ser utilizado sólo para ésta reunión y no tenía un significado profundo. Pero resultó que se extendió por la red de forma viral y se convirtió en el nombre de facto de una tendencia de las bases de datos no relacionales y distribuidas.

El término “NoSQL” tiene un origen absolutamente natural y éste no está avalado por una institución científica. Se considera que el término esta lejos de su completa definición, hay autores como Pramod J. Sadalage y Martin Fowler que trataron de agrupar y organizar todo el conocimiento sobre el mundo NoSQL en el libro “NoSQL destilada“.

Fuentes: