Read in English · Lire en français · Auf Deutsch lesen
Sección 6.6 de 6.8 · Avanzado · 30 min de lectura
Modelos de consistencia, CAP y PACELC
Videolección
5 min · narrado en inglés, con subtítulosSolo escuchar (audio)
Leer la transcripción
Cuando los datos se copian, las copias pueden discrepar. En esta lección aprenderás los principales modelos de consistencia, lo que dice realmente el teorema CAP, el compromiso cotidiano que añade PACELC y cómo elegir.
Imagina una tienda con tres sucursales. Cada una tiene una copia de la lista de existencias, y se llaman por teléfono para comunicarse los cambios. Si la línea se corta y un cliente pregunta en una sucursal por la última bicicleta, esta puede decir: no puedo estar seguro, espere, por favor. O puede responder con su propia lista y arriesgarse a vender una bicicleta que otra sucursal acaba de vender. Incluso cuando los teléfonos funcionan, consultar antes con las demás hace esperar a los clientes. Los sistemas distribuidos se enfrentan exactamente a estas opciones, y la correcta depende de lo que costaría una respuesta equivocada.
Un modelo de consistencia es el contrato que dice qué discrepancias entre copias pueden observar los clientes. Cuidado con esta palabra tan cargada de significados. La C de ACID significa pasar de un estado válido a otro. En CAP, siglas en inglés de consistencia, disponibilidad y tolerancia a particiones, la C es más limitada: cada lectura se comporta como si hubiera una única copia actualizada.
Esta es la escalera, del más fuerte al más débil. Linealizable se comporta como si hubiera una sola copia: una vez completada una escritura, todas las lecturas posteriores la ven. Si dos clientes intentan canjear el último código de descuento, exactamente uno lo consigue. Secuencial mantiene un orden acordado de las escrituras, pero una lectura puede estar ligeramente desactualizada. Causal solo exige que las causas se vean antes que los efectos. La respuesta de un restaurante en el chat del pedido nunca debe aparecer sin la pregunta del cliente. Las garantías de sesión son promesas a un solo cliente. Después de cambiar tu dirección, ves la nueva. Y una vez que has visto en reparto, nunca vuelves a ver en preparación. Eventual es la garantía útil más débil: si cesan las escrituras, todas las réplicas acaban coincidiendo. No dice cuánto tarda eso. Cada peldaño hacia abajo significa menos coordinación y menos latencia, y los modelos más débiles siguen funcionando durante una partición de red.
Ahora, el teorema CAP, con un sistema de venta de entradas. El cliente uno compra el asiento catorce C a través de la réplica A, que lo registra como vendido. Después, una partición de red aísla la réplica A de la réplica B, así que B no puede enterarse de la venta. El cliente dos pregunta a la réplica B si el asiento catorce C está libre. B debe elegir. Puede elegir la consistencia: negarse o agotar el tiempo de espera, y decir que lo intente más tarde. O puede elegir la disponibilidad: responder que el asiento está libre. Ese dato es obsoleto, y el asiento puede venderse dos veces.
Elige dos de los tres es una mala interpretación. En cualquier sistema en red, las particiones ocurren lo elijas o no. La única elección es cómo comportarse cuando ocurren. Las particiones son poco frecuentes, así que la mayor parte del tiempo un sistema puede ofrecer ambas cosas. La elección solo se aplica durante una partición, y puede ser distinta para cada operación. Así que diseña para las particiones: detéctalas, limita algunas operaciones, como aceptar pedidos pero aplazar los reembolsos, y después fusiona el estado y compensa los errores. PACELC añade lo que CAP deja fuera. Si hay una partición, elige disponibilidad o consistencia. En caso contrario, en funcionamiento normal, elige latencia o consistencia, porque las lecturas consistentes necesitan coordinación, y la pagas en cada solicitud.
Algunos almacenes te permiten ajustarlo con aritmética. Con N réplicas, una escritura se confirma cuando W la han almacenado, y una lectura consulta R réplicas y se queda con la versión más reciente. Aquí N es tres, y W y R valen dos. El escritor fija un precio de doce, y las réplicas uno y dos lo confirman. La réplica tres está atrasada y todavía tiene diez. El lector recoge respuestas de dos réplicas: la réplica tres, atrasada, y la réplica dos. Como R más W es mayor que N, los dos conjuntos deben solaparse. Aquí, la réplica dos está en ambos. Así que el lector ve la versión más reciente y devuelve doce. Pero el solapamiento por sí solo no es linealizable. Por ejemplo, los relojes que no coinciden pueden hacer que una escritura posterior pierda. Por eso la plataforma también cobra a los clientes el precio guardado en el pedido durante el proceso de pago.
Así que pregunta, para cada dato, qué sale mal si un cliente ve un valor obsoleto, y cuánto cuesta. El dinero, el último asiento al abrirse la venta y un nombre de usuario único justifican la consistencia fuerte. La dirección del propio cliente y el estado del pedido solo necesitan garantías de sesión, que son baratas: por ejemplo, leer desde el líder durante unos segundos después de que ese usuario escriba. Un chat con el restaurante necesita orden causal. Y los "me gusta", las valoraciones y el punto del repartidor en el mapa pueden ser eventuales. Pero la consistencia eventual es visible para los usuarios, así que requiere decisiones de producto, no solo técnicas.
La sección completa analiza las opciones de quórum y muestra cómo se pueden configurar cuatro bases de datos conocidas. A continuación, en la Sección seis punto siete, veremos las sagas y las transacciones distribuidas. Nos vemos allí.
Lo que necesitas saber
- Un modelo de consistencia es el contrato que dice qué valores obsoletos o reordenados pueden observar los clientes; la C de CAP (copia única, linealizable) es distinta de la C de ACID (estado válido) y de los niveles de aislamiento.
- De más fuerte a más débil: linealizable (una copia, orden en tiempo real), secuencial (un orden acordado), causal (las causas antes que los efectos), garantías de sesión como leer tus propias escrituras y lecturas monótonas, y eventual (convergencia si cesan las escrituras).
- El teorema CAP (la conjetura de Brewer de 2000, demostrada por Gilbert y Lynch en 2002) dice que, durante una partición de red, un sistema replicado debe elegir, para cada solicitud, entre consistencia y disponibilidad; las particiones no son opcionales, así que "elige dos de tres" es una mala interpretación.
- El artículo de Brewer de 2012 recomienda detectar las particiones, funcionar en un modo de partición explícito y recuperarse después con fusiones y compensaciones, eligiendo de forma distinta para operaciones distintas.
- PACELC (Abadi, 2010 y 2012) añade que, en caso contrario (else), sin partición, los sistemas intercambian latencia por consistencia en cada solicitud.
- Con N réplicas, W confirmaciones de escritura y R respuestas de lectura, elegir R + W > N hace que los conjuntos de lectura y de escritura se solapen, pero los quórums por sí solos no son linealizables.
- Elige la consistencia según el caso de uso: fuerte para el dinero, los recursos únicos y los invariantes; garantías de sesión para los datos propios de un usuario; eventual para contadores, feeds y posiciones.
Qué significa "consistente" cuando los datos se copian
En cuanto un sistema guarda más de una copia de un dato, en réplicas de zonas distintas, en cachés o en otros servicios, las copias pueden discrepar durante un tiempo. Un modelo de consistencia es el contrato que dice qué discrepancias pueden observar los clientes. Es una promesa sobre lo que pueden devolver las lecturas dadas las escrituras que han ocurrido y, por tanto, una promesa sobre qué sorpresas debe manejar el código de la aplicación.
Cuidado con esta palabra tan cargada de significados. La C de ACID (Sección 0.5) significa que una transacción lleva la base de datos de un estado válido a otro, respetando reglas como "un saldo nunca baja de cero". La C de CAP significa algo distinto y más limitado: cada lectura se comporta como si hubiera una única copia actualizada. Los niveles de aislamiento de las bases de datos, como serializable o read committed, son una tercera familia, referida a las transacciones concurrentes; se tratan en transacciones y aislamiento. Esta sección trata de las garantías de los datos replicados.
Modelos de consistencia, del más fuerte al más débil
La linealizabilidad, definida por Maurice Herlihy y Jeannette Wing en 1990, es el modelo de un solo objeto más fuerte. Cada operación parece surtir efecto instantáneamente en algún momento entre su inicio y su fin, y todos los clientes ven el mismo orden, que respeta el tiempo real: una vez completada una escritura, toda lectura que empiece después la ve, o ve algo más reciente. El sistema se comporta como si hubiera una sola copia. Ejemplo de reparto de comida: dos clientes intentan canjear el último código de descuento; con un almacén linealizable, exactamente uno lo consigue y el otro ve que ya no está, sea cual sea la réplica a la que llegue.
La consistencia secuencial, definida por Leslie Lamport en 1979 para multiprocesadores, mantiene el orden global único y mantiene las operaciones de cada cliente en el orden en que ese cliente las emitió, pero elimina el requisito de tiempo real. Un cliente puede leer un valor ligeramente desactualizado, siempre que todos estén de acuerdo en el orden de todas las escrituras. Las bases de datos distribuidas rara vez la ofrecen por su nombre, pero explica la diferencia entre "un orden acordado" y "un orden acordado que coincide con el reloj".
La consistencia causal solo exige que las operaciones relacionadas causalmente se vean en el mismo orden por parte de todos: si escribir B dependió de haber visto A, nadie puede ver B sin A. Las escrituras concurrentes y no relacionadas pueden verse en órdenes distintos por clientes distintos. Ejemplo: un restaurante responde "Sí, es sin gluten" a la pregunta de un cliente en el chat del pedido; nadie debería ver nunca la respuesta sin la pregunta. La consistencia causal resulta atractiva porque el mapa de modelos de consistencia de Jepsen, muy utilizado, la clasifica como alcanzable con disponibilidad adherente (sticky): puede seguir funcionando durante una partición siempre que cada cliente permanezca con la misma réplica.
Las garantías de sesión, descritas por Douglas Terry y sus colegas en 1994, son promesas más débiles, por cliente, que eliminan las anomalías más confusas. Leer tus propias escrituras (read-your-writes): después de que un cliente cambie la dirección de entrega, la siguiente lectura de ese cliente muestra la nueva dirección, aunque otros usuarios la vean más tarde. Lecturas monótonas: una vez que un cliente ha visto el estado del pedido "en reparto", nunca ve después "en preparación" porque una lectura posterior llegó a una réplica retrasada. (Otras dos garantías, las escrituras monótonas y las escrituras que siguen a las lecturas, restringen el orden en que se aplican las escrituras de un cliente.)
La consistencia eventual, popularizada por Werner Vogels en 2008, es la garantía útil más débil: si no llegan escrituras nuevas, todas las réplicas acaban convergiendo en el mismo valor. No dice nada sobre cuánto tarda eso ni sobre qué puede leerse mientras tanto, y una implementación básica que resuelve las escrituras en conflicto conservando la de marca de tiempo más reciente, conocida como last write wins (gana la última escritura), descarta la otra en silencio. Las formas más fuertes, como la consistencia eventual fuerte con tipos de datos replicados libres de conflictos (CRDT), garantizan que las réplicas que han recibido las mismas actualizaciones tengan el mismo estado, usando tipos de datos cuyas actualizaciones concurrentes siempre se fusionan, como contadores y conjuntos.
La escalera de la consistencia
CAP: lo que dice realmente
Eric Brewer presentó la idea de CAP como una conjetura en su conferencia principal en el ACM Symposium on Principles of Distributed Computing (PODC) de 2000. En 2002, Seth Gilbert y Nancy Lynch publicaron una demostración formal, que la convirtió en un teorema para sus definiciones precisas. Consistencia significaba linealizabilidad. Disponibilidad significaba que toda solicitud recibida por un nodo que no ha fallado debe producir una respuesta. Tolerancia a particiones significaba que el sistema cumple sus promesas incluso cuando la red pierde un número arbitrario de mensajes entre nodos.
Leído con atención, el teorema CAP es limitado. Dice que, cuando se produce una partición de red, de modo que algunos nodos no pueden comunicarse con otros, un sistema replicado debe elegir para cada solicitud entre consistencia y disponibilidad. Un nodo aislado de las últimas escrituras puede negarse a responder (o esperar a que la partición se resuelva), preservando la consistencia, o responder con lo que tiene, preservando la disponibilidad a riesgo de devolver datos obsoletos o de aceptar escrituras en conflicto. El diagrama muestra el dilema en un sistema de venta de entradas que vende el asiento 14C.
Varias interpretaciones populares son erróneas. "Elige dos de los tres" sugiere que la tolerancia a particiones es opcional, pero en cualquier sistema que se comunica a través de una red las particiones ocurren lo elijas o no; la única elección real es cómo comportarse cuando ocurren. Un sistema llamado "CA" es uno que no ha decidido qué hacer cuando se produce una partición; eso solo es defendible donde las particiones son prácticamente imposibles, como en un único nodo. "Nuestra base de datos es CP (o AP)" suele ser impreciso: la disponibilidad de CAP es una propiedad muy fuerte que muchos sistemas comercializados como de alta disponibilidad no tienen, y muchos sistemas llamados CP tampoco son linealizables. Martin Kleppmann sostuvo en 2015 que las bases de datos no deberían etiquetarse en absoluto como CP o AP, porque la mayoría no encaja en ninguna de las dos definiciones y su comportamiento depende de la configuración. "CAP explica nuestra latencia" también es erróneo: CAP no dice nada sobre lo que ocurre cuando no hay partición, que es la mayor parte del tiempo.
La elección de CAP, en concreto
CAP doce años después
En 2012, en un artículo de IEEE Computer titulado "CAP Twelve Years Later: How the Rules Have Changed", el propio Brewer explicó que el planteamiento de dos de tres había confundido a la gente. Las particiones son poco frecuentes, así que un sistema puede ofrecer consistencia y disponibilidad casi todo el tiempo; la elección solo se aplica durante una partición, y solo a las operaciones afectadas. Tampoco hace falta que la elección sea global: operaciones distintas y datos distintos pueden elegir de forma distinta.
Brewer recomendó diseñar explícitamente para las particiones en tres pasos: detectar la partición, entrar en un modo de partición explícito en el que algunas operaciones se limitan (por ejemplo, aceptar pedidos pero aplazar los reembolsos) y ejecutar después un proceso de recuperación que fusione el estado y compense los errores cometidos durante la partición. También señaló que la C de CAP es la consistencia de copia única, un subconjunto más estricto de lo que protege la C de ACID, y que invariantes como "no vender nunca de más" pueden tener que repararse a posteriori. Este planteamiento conduce directamente a las compensaciones a nivel de negocio de las sagas: una aerolínea que vende más plazas de las que tiene un vuelo compensa al pasajero en lugar de rechazar todas las reservas durante un fallo de red.
PACELC: el compromiso que pagas cada día
Daniel Abadi señaló en una entrada de blog de 2010, y en un artículo de IEEE Computer de 2012, "Consistency Tradeoffs in Modern Distributed Database System Design: CAP is Only Part of the Story", que CAP ignora el compromiso al que se enfrentan realmente los diseñadores la mayor parte del tiempo. PACELC se lee así: si hay una Partición, elige entre disponibilidad (Availability) y Consistencia; en caso contrario (Else), en funcionamiento normal, elige entre Latencia y Consistencia.
La mitad del "else" es la aportación importante. Para que una lectura sea consistente, un sistema replicado debe coordinarse: enviar la escritura a otras réplicas y esperar las confirmaciones, o dirigir todas las lecturas a un líder, o contactar con varias réplicas y comparar. Cada una de esas opciones cuesta viajes de ida y vuelta por la red, y entre regiones un viaje de ida y vuelta puede costar decenas o incluso cientos de milisegundos. Un sistema que responde desde la réplica más cercana sin coordinarse es más rápido, pero puede devolver datos obsoletos. Ese compromiso se paga en cada solicitud, haya partición o no.
A menudo se citan clasificaciones PACELC, como PA/EL para los sistemas ajustados para la velocidad y la disponibilidad, y PC/EC para los sistemas que siempre prefieren la consistencia. Trátalas como descripciones de una configuración, no de un producto: la misma base de datos puede ser PA/EL en un despliegue y PC/EC en otro, según los ajustes elegidos por tabla, por consulta o por solicitud.
Quórums: ajustar la consistencia con aritmética
Los almacenes replicados sin líder, al estilo del artículo de Dynamo de Amazon (2007), permiten que cada operación elija cuántas réplicas intervienen. Con N réplicas de un elemento, una escritura se confirma cuando W réplicas la han almacenado, y una lectura recoge respuestas de R réplicas y devuelve la versión más reciente entre ellas. Si R + W > N, todo conjunto de lectura se solapa con todo conjunto de escritura en al menos una réplica, así que una lectura incluirá al menos una copia de la última escritura confirmada.
La elección de R y W intercambia consistencia, latencia y disponibilidad. Valores más bajos significan esperar a menos réplicas, y más rápidas, y tolerar más fallos, a cambio de posibles lecturas obsoletas. Valores más altos significan lo contrario. De todos modos, las escrituras suelen enviarse a las N réplicas; W solo decide cuántas confirmaciones espera el cliente.
El solapamiento del quórum es necesario para obtener lecturas actualizadas, pero no es, por sí solo, linealizabilidad. Las escrituras concurrentes pueden ordenarse con marcas de tiempo de relojes que no coinciden, de modo que una escritura posterior puede perder con last-write-wins. Una escritura que falló después de llegar a algunas réplicas puede seguir siendo visible en ellas. Los quórums "laxos" (sloppy), que aceptan escrituras en nodos sustitutos durante los fallos, rompen el solapamiento. Y dos lecturas que se solapan con una escritura todavía en curso pueden ver el valor nuevo y luego el antiguo, a menos que el lector repare las réplicas retrasadas antes de devolver el resultado. Los almacenes que necesitan una verdadera semántica de comparar e intercambiar (compare-and-set) añaden un protocolo de consenso, como las transacciones ligeras basadas en Paxos de Apache Cassandra, solo para esas operaciones.
Por qué funciona R + W > N
Cómo se pueden configurar bases de datos conocidas
Los productos reales rara vez se sitúan en un solo punto de la escalera. Exponen ajustes, y la descripción correcta es "cómo está configurado este despliegue". Siguen cuatro ejemplos habituales; consulta la documentación actual de la versión que ejecutas, porque los valores por defecto cambian de una versión a otra.
Consistencia configurable en cuatro bases de datos muy utilizadas (comportamiento documentado en el momento de escribir esto)
| Base de datos | Comportamiento típico por defecto | Ajustes que refuerzan la consistencia | Qué vigilar |
|---|---|---|---|
| PostgreSQL con replicación en streaming | Un único primario recibe todas las escrituras; la replicación a los servidores en espera (standbys) es asíncrona por defecto, así que las lecturas desde un standby pueden estar obsoletas. | synchronous_standby_names con synchronous_commit (por ejemplo, remote_apply) hace que una confirmación espere hasta que los standbys la tengan; lee desde el primario para leer tus propias escrituras. | La replicación síncrona añade latencia a las confirmaciones, y las escrituras se detienen si los standbys requeridos son inaccesibles. |
| Conjunto de réplicas de MongoDB | En la mayoría de los despliegues, las escrituras requieren por defecto la confirmación de una mayoría; las lecturas desde el primario usan por defecto el read concern local, que puede devolver datos que más tarde se revierten. | Read concern majority o linearizable; sesiones causalmente consistentes cuando tanto las lecturas como las escrituras usan majority. | Leer desde los secundarios (read preference) intercambia actualidad de los datos por latencia y carga. |
| Apache Cassandra | El nivel de consistencia se elige por solicitud (ONE, QUORUM, LOCAL_QUORUM, ALL y otros); los conflictos se resuelven con marcas de tiempo según last-write-wins. | QUORUM (o LOCAL_QUORUM dentro de un centro de datos) tanto para lecturas como para escrituras, de modo que R + W > factor de replicación; transacciones ligeras para comparar e intercambiar (compare-and-set). | El desfase de los relojes afecta a last-write-wins; LOCAL_QUORUM no da ninguna garantía entre centros de datos. |
| Amazon DynamoDB | Las lecturas son eventualmente consistentes por defecto; las tablas globales se replican entre regiones de forma asíncrona por defecto. | ConsistentRead=true en tablas e índices secundarios locales; tablas globales con consistencia fuerte multirregión (disponible de forma general desde 2025). | Las lecturas fuertemente consistentes no están disponibles en los índices secundarios globales, consumen el doble de capacidad de lectura y pueden ser más lentas. |
Elegir la consistencia según el caso de uso
El hábito más útil es dejar de preguntar "¿es consistente nuestro sistema?" y preguntar, para cada dato y cada operación, qué sale mal si un cliente ve un valor obsoleto o reordenado, y cuánto cuesta. El movimiento de dinero, los recursos únicos y los invariantes suelen justificar la consistencia fuerte y su latencia. Los contadores, los feeds, las recomendaciones y la analítica normalmente no. Muchas anomalías que ve el usuario desaparecen solo con las garantías de sesión, que son baratas: dirige las lecturas de un usuario al primario durante unos segundos después de que ese usuario escriba, o lleva un token de versión en la sesión y espera hasta que la réplica se haya puesto al día con él.
Necesidades de consistencia por caso de uso
| Caso de uso | Costo de una lectura obsoleta o reordenada | Garantía razonable | Mecanismo típico |
|---|---|---|---|
| Saldo bancario antes de una retirada | Descubierto por encima del límite; dinero perdido | Linealizable (y transacciones serializables) | Un único líder para la cuenta, replicación síncrona o consenso |
| Último asiento o entrada al abrirse la venta | Vender un asiento dos veces; reembolsos y clientes enfadados | Linealizable por asiento | Escritura condicional (compare-and-set) sobre el registro del asiento |
| Nombre de usuario único al registrarse | Dos cuentas con el mismo nombre | Linealizable en la comprobación de unicidad | Restricción de unicidad en una sola base de datos, o un registro respaldado por consenso |
| Dirección de entrega del propio cliente después de editarla | La comida se envía a la dirección antigua | Leer tus propias escrituras (read-your-writes) | Leer desde el líder después de una escritura, o un token de versión en la sesión |
| Estado del pedido que se muestra al cliente | El estado parece retroceder; confusión y llamadas al servicio de atención | Lecturas monótonas más leer tus propias escrituras | Enrutamiento fijo (sticky) a una réplica, o tokens de versión |
| Chat del restaurante con el cliente | Una respuesta aparece antes que su pregunta | Causal | Almacén causalmente consistente, u ordenación por conversación |
| Carrito de la compra | Reaparece un artículo eliminado; algo molesto | Eventual, con fusión | Aceptar siempre los añadidos; fusionar versiones (el ejemplo del artículo de Dynamo) |
| Número de "me gusta" o valoración del restaurante | El recuento se desvía en unos pocos durante unos segundos | Eventual | Replicación asíncrona, contadores o CRDT |
| Ubicación del repartidor en el mapa | El punto va unos segundos por detrás | Eventual, gana el último valor | Escrituras de baja latencia en la réplica más cercana; las posiciones antiguas se descartan |
Comprueba lo que has entendido
¿Cuál es la diferencia entre la linealizabilidad y la consistencia secuencial?
Ambas exigen un único orden de operaciones en el que todos los clientes estén de acuerdo y que respete el orden propio de cada cliente; la linealizabilidad exige además que ese orden respete el tiempo real, de modo que una lectura que empieza después de completarse una escritura debe verla.
¿Por qué una base de datos distribuida "CA" no es una elección con sentido?
Porque las particiones de red ocurren en cualquier sistema que se comunica a través de una red; un sistema que supone que nunca se producen simplemente no ha decidido qué hará cuando se produzcan.
Con N = 5 y W = 2, ¿cuál es el R más pequeño que garantiza que los conjuntos de lectura y de escritura se solapen?
R = 4, porque R + W debe ser mayor que 5.
Un usuario edita su perfil y la página se recarga mostrando la versión antigua, aunque no importa que otros usuarios la vean con retraso. ¿Qué garantía falta y cuál es una solución barata?
Leer tus propias escrituras; dirige las lecturas de ese usuario al líder durante un breve tiempo después de una escritura, o lleva un token de versión y espera a una réplica que se haya puesto al día.
Fuentes y lecturas recomendadas
- Eric Brewer: CAP Twelve Years Later: How the Rules Have Changed (InfoQ reprint of the IEEE Computer article)
- Daniel Abadi: Problems with CAP, and Yahoo's little known NoSQL system (2010, origin of PACELC)
- Jepsen: Consistency models
- Martin Kleppmann: Please stop calling databases CP or AP (2015)
- Apache Cassandra documentation: Dynamo (tunable consistency and quorums)
¿Tienes una pregunta sobre esta sección? ArchitectBot, el asistente de estudio con IA del curso, responde primero a partir del curso.
Pregunta: “Vamos a añadir réplicas de lectura a nuestra base de datos de pedidos. ¿Qué pantallas de la app del cliente necesitan leer tus propias escrituras y cómo lo conseguimos a bajo costo?”