📊¿Qué es el teorema CAP?


Este teorema dice que un sistema distribuido solo puedes garantizar simultáneamente dos de estas tres propiedades:
Consistency (consistencia)
Availability (disponibilidad)
Partition tolerance (tolerancia a particiones)
¿Pero qué significan estas propiedades?
Consistencia
Todos los nodos/usuarios del sistema ven los mismos datos al mismo tiempo. Cuando una escritura se realiza en un nodo, todas las lecturas siguientes van a devolver el valor actualizado.
Disponibilidad
Cada petición realizada a un nodo disponible recibe una respuesta. Sin tener la garantía de que contenga la versión más actualizada de los datos.
Tolerancia a particiones
El sistema puede seguir en funcionamiento aunque parte de la red esté caída o parte de los mensajes se pierdan.
¿Dónde está la trampa?
Pues que, a no ser que estemos trabajando con una arquitectura monolito, seguramente estemos ante un sistema distribuido y, por lo tanto, la tolerancia a particiones es obligatoria. Por lo tanto, ya hemos elegido una de las dos propiedades que podemos tener.
Así que la pregunta clave termina siendo:
Cuando ocurre una partición en la red, ¿queremos priorizar la disponibilidad o la consistencia?
Imaginémonos el siguiente caso por un momento: nuestro sistema es una aplicación web que se utiliza en todo el mundo y tenemos una base de datos con todos los usuarios de nuestra aplicación en el mundo y, desplegadas, hay una instancia en Estados Unidos y otra en Europa. Dichas bases de datos son una réplica la una de la otra y están sincronizadas.
Pues ahora va John y quiere actualizar su perfil, por ejemplo, cambiar la biografía que aparece. Justo después de esto, va Paco y quiere leer la información que tiene John en su perfil. Ocurriría algo así:
John se conecta al servidor de Estados Unidos y actualiza su biografía.
La base de datos de Europa se sincroniza con la de EEUU y se trae los cambios.
Cuando Paco ve el perfil de John, ve su biografía actualizada.
Todo funciona de maravilla hasta que nos encontramos con una partición en la red. La conexión entre el clúster de Estadios Unidos y el de Europa se rompe.
Ahora bien, si consideramos el ejemplo anterior de nuevo, pero con esta partición de red, ¿qué deberíamos hacer?
Opción A: devolver un error porque no podemos garantizar que nuestros datos estén actualizados (elegimos consistencia)
Opción B: devolver datos que podrían estar desactualizados (elegimos disponibilidad)
Pues esta es la clave del teorema de CAP, la respuesta a esta pregunta definirá si esta parte de tu sistema prioriza la consistencia o la disponibilidad.
En este caso está claro, devolveríamos la biografía del usuario John, aunque no podamos asegurar que sea la versión más actualizada.
¿Cuándo elijo consistencia y cuando disponibilidad?
La realidad es que en la mayoría de sistemas van a tolerar algo de inconsistencia y deberían priorizar la disponibilidad. En estos casos lo que se llama eventual consistency es suficiente. Esto quiere decir que el sistema llegará eventualmente en algún punto a ser consistente, pero puede tardar segundos o incluso minutos.
Elegiremos consistencia en sistemas como:
Un sistema que tenga reserva de tickets (Ticketmaster, Skyscanner): imagínate que hemos comprado tickets para un vuelo, pero a la hora de comprarlos hubo una partición de red y otra persona también los vio disponibles y compró los mismos tickets. Al aeropuerto llegarán dos personas con el mismo ticket.
Inventario de una tienda e-commerce: si en una tienda como Amazon aparece que queda una sola Nintendo Switch 2 y la compras cuando hay una partición de red, quizás más de un usuario ha comprado la última unidad y alguien se queda sin ella.
Sistemas de finanzas: los sistemas relacionados con stocks tienen que enseñar los últimos datos actualizados o si no, podrían haber problemas relacionados con los precios a los que se compraron o vendieron acciones.
Elegiremos disponibilidad en sistemas como:
Redes sociales (Instagram): si un usuario actualiza su biografía, no pasa nada si otro usuario tarda un poquito más en verla actualizada.
Plataformas de contenido (Netflix o Youtube): si alguien actualiza el nombre de una película en otro idioma, no pasa nada porque el título antiguo aparezca un poco más de tiempo.
Páginas de reseñas (Google Maps): si un restaurante actualiza su horario, es mejor enseñar el horario antiguo que no enseñar nada.
Así que, de nuevo, ya para terminar, la pregunta que uno se tiene que preguntar es:
¿Sería un desastre si los usuarios viesen datos inconsistentes durante un rato?
Si la respuesta es sí, elige consistencia. Si es no, elige disponibilidad.
Fuentes:
Subscribe to my newsletter
Read articles from Juanjo Requena directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Juanjo Requena
Juanjo Requena
👋 Hey there! I'm Juanjo, a Backend Software Engineer with a focus on API development. My colleagues know me as someone committed to quality and attention to detail, my friends know me as a funny guy who knows good places to eat food. This blog tries to blend both sides of me.