{"id":3980,"date":"2017-09-07T16:42:02","date_gmt":"2017-09-07T23:42:02","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=3980"},"modified":"2025-06-13T20:46:36","modified_gmt":"2025-06-14T03:46:36","slug":"couchbases-history-everything-dcp","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/couchbases-history-everything-dcp\/","title":{"rendered":"Historia de todo en Couchbase: DCP"},"content":{"rendered":"<p><em>M. David Allen es un ingeniero de software y emprendedor que, durante m\u00e1s de una d\u00e9cada, ha trabajado con casi todos los lenguajes de programaci\u00f3n y sistemas de bases de datos que ha tenido a su alcance. David ha trabajado anteriormente en muchos sectores, como el financiero, el sanitario y el gubernamental, centr\u00e1ndose normalmente en retos de integraci\u00f3n de datos a gran escala, investigaci\u00f3n aplicada en transici\u00f3n e innovaci\u00f3n de nuevas tecnolog\u00edas. Tiene un m\u00e1ster de la Virginia Commonwealth University, pero desde que abandon\u00f3 la educaci\u00f3n formal sigue siendo un estudiante permanente de tecnolog\u00eda.<\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-5662\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/09\/Simple-Small-Headshot-450x300-compressed-300x200.png\" alt=\"\" width=\"458\" height=\"305\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/09\/Simple-Small-Headshot-450x300-compressed-300x200.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/09\/Simple-Small-Headshot-450x300-compressed-400x267.png 400w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/09\/Simple-Small-Headshot-450x300-compressed.png 450w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/09\/Simple-Small-Headshot-450x300-compressed-20x13.png 20w\" sizes=\"auto, (max-width: 458px) 100vw, 458px\" \/><\/p>\n<h2>Historia de todo en Couchbase: DCP<\/h2>\n<p>Escondido detr\u00e1s de un acr\u00f3nimo DCP (database change protocol), Couchbase tiene un superpoder secreto. La mayor\u00eda de la gente piensa en las bases de datos como ubicaciones de almacenamiento de datos en un momento determinado. Pero con <u><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/3.x\/admin\/Concepts\/dcp.html\" target=\"_blank\" rel=\"noopener noreferrer\">Protocolo de cambio de base de datos (DCP)<\/a><\/u>Un cluster Couchbase puede ser visto como un flujo continuo de cambios.<\/p>\n<p>Esencialmente, Couchbase puede \"rebobinar la historia\" y reproducir todo lo ocurrido en la base de datos desde el principio. Al hacerlo, puede resolver cualquier estado interno desde entonces. En este art\u00edculo vamos a cubrir por qu\u00e9 alguien querr\u00eda hacer una cosa tan loca en primer lugar, y c\u00f3mo podemos explotar este superpoder para hacer cosas extra cool con nuestros documentos.<\/p>\n<h2>\u00bfQu\u00e9 es DCP?<\/h2>\n<p>Como base de datos en cl\u00faster, Couchbase aborda toda una serie de problemas especializados que la arquitectura de bases de datos tiene que resolver. Tiene que mantener varios nodos sincronizados entre s\u00ed, incluso si uno de ellos falla temporalmente o se produce una interrupci\u00f3n de la red entre ellos. Tambi\u00e9n tiene que ser r\u00e1pida, lo suficiente como para recibir grandes vol\u00famenes de documentos nuevos y gestionar las consultas a medida que surgen.<\/p>\n<p>Parte del dise\u00f1o subyacente de Couchbase y la forma en que esto es posible es a trav\u00e9s de los cambios de flujo en un <u><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/architecture\/storage-architecture.html\" target=\"_blank\" rel=\"noopener noreferrer\">enfoque de s\u00f3lo ap\u00e9ndice<\/a><\/u><a target=\"_blank\" rel=\"noopener noreferrer\">[1]<\/a>. Esto significa que cuando cambias un documento, Couchbase no busca el documento y lo modifica en el disco. En lugar de eso, simplemente a\u00f1ade a un registro de claves y valores el resultado de tu mutaci\u00f3n, y sigue movi\u00e9ndose. De esta forma, las escrituras pueden hacerse muy r\u00e1pido, y es m\u00e1s f\u00e1cil coordinar m\u00faltiples nodos.<\/p>\n<p>Si est\u00e1 familiarizado con las bases de datos relacionales, el planteamiento de DCP es algo similar al de <u><a href=\"https:\/\/www.postgresql.org\/docs\/9.1\/static\/wal-intro.html\" target=\"_blank\" rel=\"noopener noreferrer\">registro de escritura anticipada<\/a><\/u>\u00a0que se ven en otros programas.<\/p>\n<h2>\u00bfPor qu\u00e9 preocuparse de c\u00f3mo lo hace Couchbase internamente?<\/h2>\n<p>A cierto nivel, querr\u00e1 que su base de datos se preocupe de estas cosas <em>para<\/em>\u00a0para que t\u00fa no tengas que hacerlo. Pero en el caso de DCP, nos importa porque podemos vampiro aprovechar ese flujo de eventos y hacer todo tipo de cosas interesantes con \u00e9l, como:<\/p>\n<p><strong>Replicaci\u00f3n de datos en bases de datos completamente distintas.<\/strong>\u00a0Couchbase ya dispone de una serie de <u><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/4.1\/connectors\/intro.html#concept_iy1_2rg_2s\" target=\"_blank\" rel=\"noopener noreferrer\">conectores<\/a><\/u>como Elasticsearch. Puedes configurar un cluster separado de Elasticsearch, y hacer que contenga una copia de todos los datos de Couchbase, exponiendo todos tus datos a las caracter\u00edsticas que la otra base de datos puede proporcionarte. Mantener estos dos clusters normalmente ser\u00eda un problema de sincronizaci\u00f3n bastante peliagudo, pero como los conectores se alimentan principalmente de DCP, podemos pensar en los mensajes de DCP como un flujo de \"git commits\" que mantienen continuamente actualizada la otra base de datos.<\/p>\n<p><strong>Uso de enfoques basados en colas e integraci\u00f3n con otros microservicios.<\/strong>\u00a0Si puedes escribir un trozo de c\u00f3digo para escuchar ese flujo DCP, tambi\u00e9n puedes filtrarlo s\u00f3lo a los mensajes que te interesan. Tal vez sea s\u00f3lo cuando algo se elimina, o s\u00f3lo las actualizaciones de un determinado tipo de documento. En cualquier caso, puedes usar un cliente DCP para filtrar ese flujo de mensajes, y publicar los mensajes extra en una cola RabbitMQ, <u><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/4.1\/connectors\/kafka-2.0\/kafka-intro.html\" target=\"_blank\" rel=\"noopener noreferrer\">un tema Kafka<\/a><\/u>o lo que necesites. Esto puede ser muy \u00fatil para implementar otra l\u00f3gica de negocio compleja. Por ejemplo, imaginemos una compa\u00f1\u00eda de seguros que, dependiendo del estado del cliente, necesita activar alguna l\u00f3gica adicional relacionada con el cumplimiento. Escuche las mutaciones de los documentos del cliente, filtre por estado, publique en la cola correcta y deje que alg\u00fan otro servicio se preocupe de la diferencia entre lo que debe hacerse para los clientes de Virginia frente a los de Maryland.<\/p>\n<p><strong>An\u00e1lisis de series temporales\/revisiones.<\/strong>\u00a0Cada valor de su base de datos cambia con el tiempo. Algunos se escriben una vez y se olvidan. Otros pueden actualizarse con frecuencia. Para los que se actualizan con frecuencia, DCP le permite tratar cada elemento como un <u><a href=\"https:\/\/en.wikipedia.org\/wiki\/Time_series\" target=\"_blank\" rel=\"noopener noreferrer\">series temporales<\/a><\/u>. Se sabe cu\u00e1l era el valor antes, cu\u00e1ndo cambi\u00f3 y a qu\u00e9 cambi\u00f3. Esto permite familias enteras de interesantes an\u00e1lisis de datos posteriores. \u00bfAdivinar\u00eda que la gente valora m\u00e1s cervezas en su sitio los viernes y s\u00e1bados por la noche, o los martes por la ma\u00f1ana?<\/p>\n<p>Esencialmente, DCP se puede utilizar como una especie de pegamento arquitect\u00f3nico; una forma de sacar los datos de Couchbase y llevarlos a otros sistemas, y eso hace que Couchbase sea m\u00e1s f\u00e1cil y flexible de integrar con otros sistemas.<\/p>\n<p>Por \u00faltimo, hay que decir que la funci\u00f3n est\u00e1ndar de replicaci\u00f3n entre centros de datos (XDCR) de Couchbase, que permite replicar a otro cl\u00faster de Couchbase para copias de seguridad y recuperaci\u00f3n en caso de desastre.<strong>\u00a0<\/strong><u><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/3.x\/admin\/XDCR\/xdcr-memory-replication.html\" target=\"_blank\" rel=\"noopener noreferrer\">puede utilizar DCP de manera muy similar<\/a><\/u>. As\u00ed que, en esencia, DCP no es s\u00f3lo una \"bonita caracter\u00edstica extra\", est\u00e1 realmente integrada en el n\u00facleo, desde los fundamentos de c\u00f3mo funciona la arquitectura de almacenamiento, hasta proporcionar una base para otras caracter\u00edsticas de Couchbase como XDCR.<\/p>\n<h2>\u00bfY si quisiera hacer ?<\/h2>\n<p>Vas a necesitar un cliente DCP, que no es m\u00e1s que un m\u00f3dulo de software que te permite aceptar mensajes DCP y procesarlos. En el momento de escribir esto, hay uno bueno listo para <u><a href=\"https:\/\/github.com\/couchbase\/java-dcp-client\" target=\"_blank\" rel=\"noopener noreferrer\">Java<\/a><\/u>y una para <u><a href=\"https:\/\/github.com\/couchbaselabs\/python-dcp-client\" target=\"_blank\" rel=\"noopener noreferrer\">Python<\/a><\/u>\u00a0aunque puede que est\u00e9 desfasado.<\/p>\n<h2>Algunos detalles de DCP ...<\/h2>\n<p>El DCP puede considerarse b\u00e1sicamente como un flujo de mensajes de mutaci\u00f3n y borrado. Una mutaci\u00f3n es cualquier cambio en una clave o en su contenido. Un borrado es exactamente lo que parece. <u><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/4.1\/connectors\/kafka-2.0\/kafka-intro.html\" target=\"_blank\" rel=\"noopener noreferrer\">Existen otros tipos de mensajes DCP<\/a><\/u>pero limit\u00e9monos por ahora a las supresiones y mutaciones.<\/p>\n<p>\u00bfQu\u00e9 contiene un mensaje DCP? Hay dos elementos importantes:<\/p>\n<ul>\n<li><strong>Un identificador de vBucket.<\/strong>\u00a0Entre bastidores, Couchbase no es m\u00e1s que un gran almac\u00e9n de claves\/valores. Como sabemos que es una base de datos distribuida, Couchbase trocea todas las claves de la base de datos y las asigna a diferentes \"particiones\", llamadas vBuckets. El identificador vBucket s\u00f3lo le dice a la base de datos qu\u00e9 segmento del espacio de claves est\u00e1 cambiando. <u><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/concepts\/distributed-data-management.html\" target=\"_blank\" rel=\"noopener noreferrer\">Hay mucha m\u00e1s informaci\u00f3n disponible sobre este tema<\/a><\/u>\u00a0si quieres profundizar, pero hay mucha configurabilidad en Couchbase alrededor de los vBuckets. En esta imagen, podemos ver que 9 vBuckets est\u00e1n siendo distribuidos a trav\u00e9s de 3 servidores, sin redundancia.<\/li>\n<li><strong>Un n\u00famero creciente.<\/strong>\u00a0El valor del n\u00famero no es muy importante, pero lo importante es que siempre sube. As\u00ed es como Couchbase puede ordenar todos los mensajes DCP en el tiempo, lo cual es bastante importante.<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"636\" height=\"194\" class=\"wp-image-3978\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/09\/vbuckets.png\" alt=\"vbuckets\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/09\/vbuckets.png 636w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/09\/vbuckets-300x92.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/09\/vbuckets-20x6.png 20w\" sizes=\"auto, (max-width: 636px) 100vw, 636px\" \/><\/p>\n<p><em>Fuente de la imagen: <\/em><u><a href=\"https:\/\/static.couchbaseinc.hosting.ca.onehippo.com\/images\/server\/3.x\/20170420-170703\/vbuckets.png\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/static.couchbaseinc.hosting.ca.onehippo.com\/images\/server\/3.x\/20170420-170703\/vbuckets.png<\/a><\/u><\/p>\n<h2>Nuestro sencillo caso pr\u00e1ctico<\/h2>\n<p>Tomemos como ejemplo <u><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/3.x\/admin\/Misc\/sample-bucket-beer.html\" target=\"_blank\" rel=\"noopener noreferrer\">muestra de cerveza<\/a><\/u>\u00a0como ejemplo. Los usuarios pueden valorar las cervezas; cuando la valoraci\u00f3n agregada de una cerveza alcanza un determinado umbral, los responsables de marketing quieren saberlo. Probablemente llamar\u00e1n a la cervecera y le preguntar\u00e1n si quiere anunciarse en nuestro sitio web de cerveza. O mejor a\u00fan, tal vez si una cerveza alcanza las 5 estrellas se abastezcan para la pr\u00f3xima reuni\u00f3n de empresa. En cualquier caso, quieren conocer las cervezas de 5 estrellas.<\/p>\n<p>El problema es que los chicos de marketing tienen un sistema de clientes potenciales independiente. Podemos notific\u00e1rselo con un simple mensaje HTTP a su sistema. Cuando una cerveza alcanza las 5 estrellas, avisamos a su sistema de contactos para que echen un vistazo a Foo Brew.<\/p>\n<h2>C\u00f3digo<\/h2>\n<p>El c\u00f3digo que se muestra a continuaci\u00f3n est\u00e1 adaptado del tutorial de la aplicaci\u00f3n\u00a0<u><a href=\"https:\/\/github.com\/couchbase\/java-dcp-client\" target=\"_blank\" rel=\"noopener noreferrer\">Cliente Java DCP<\/a><\/u>. Una vez que entiendes lo que ocurre, es bastante sencillo adaptarlo a tus necesidades.<\/p>\n<pre class=\"lang:default decode:true\">package com.foo.app;\r\n\r\nimport com.couchbase.client.dcp.Client;\r\n\r\nimport com.couchbase.client.dcp.message.DcpMutationMessage;\r\n\r\nimport com.couchbase.client.dcp.DataEventHandler;\r\n\r\nimport com.couchbase.client.dcp.ControlEventHandler;\r\n\r\nimport com.couchbase.client.deps.io.netty.buffer.ByteBuf;\r\n\r\nimport com.couchbase.client.dcp.transport.netty.ChannelFlowController;\r\n\r\nimport com.couchbase.client.dcp.message.DcpDeletionMessage;\r\n\r\nimport com.couchbase.client.dcp.StreamFrom;\r\n\r\nimport com.couchbase.client.dcp.StreamTo;\r\n\r\nimport java.util.concurrent.TimeUnit;\r\n\r\nimport com.couchbase.client.deps.io.netty.util.CharsetUtil;\r\n\r\nimport com.google.gson.JsonParser;\r\n\r\nimport com.google.gson.JsonObject;\r\n\r\npublic class App {\r\n\r\n\u00a0 \u00a0public static void main(String[] args) throws Exception {\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0final JsonParser parser = new JsonParser();\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0final Client client = Client.configure().hostnames(\"localhost\").bucket(\"beer-sample\").build();\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0\/\/ Don't do anything with control events in this example\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0client.controlEventHandler(new ControlEventHandler() {\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0public void onEvent(ChannelFlowController flowController, ByteBuf event) {\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0event.release();\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0}\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0});\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0client.dataEventHandler(new DataEventHandler() {\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0public void onEvent(ChannelFlowController flowController, ByteBuf event) {\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0if (DcpMutationMessage.is(event)) {\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0JsonObject obj = parser.parse(DcpMutationMessage.content(event).toString(CharsetUtil.UTF_8)).getAsJsonObject();\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0if (obj.get(\"rating\") != null &amp;&amp; obj.get(\"rating\").getAsInt() &gt; 4) {\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\/\/ OMG, marketing guys gonna love this stuff...\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0System.out.println(\"Tasty beer located: \" + obj.get(\"name\").getAsString());\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0}\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0} else if (DcpDeletionMessage.is(event)) {\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\/\/ System.out.println(\"Goodbye, tasty beer! \" + DcpDeletionMessage.toString(event));\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0}\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0event.release();\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0}\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0});\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0\/\/ Connect the sockets\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0client.connect().await();\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0\/\/ Initialize the state (start now, never stop)\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0client.initializeState(StreamFrom.BEGINNING, StreamTo.INFINITY).await();\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0\/\/ Start streaming on all partitions\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0client.startStreaming().await();\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0\/\/ Sleep for some time to print the mutations\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0\/\/ The printing happens on the IO threads!\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0Thread.sleep(TimeUnit.MINUTES.toMillis(10));\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0\/\/ Once the time is over, shutdown.\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0client.disconnect().await();\r\n\r\n\u00a0 \u00a0}\r\n\r\n}\r\n\r\n<\/pre>\n<h2><span style=\"color: #343e47;font-family: Lato, 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size: 60px\">\u00bfQu\u00e9 ocurre en este c\u00f3digo?<\/span><\/h2>\n<ul>\n<li>Conexi\u00f3n a una instancia cliente (y a un bucket concreto)<\/li>\n<li>Indique al cliente el intervalo de tiempo de los mensajes que nos interesan. Nosotros vamos a por el historial completo del cluster, pero podr\u00edamos elegir cualquier periodo de tiempo que queramos:  StreamFrom.BEGINNING, StreamTo.INFINITY<\/li>\n<li>Indica al cliente c\u00f3mo procesar un mensaje individual; \u00e9se es el c\u00f3digo dataEventHandler.<\/li>\n<li>En nuestro caso, estamos analizando el JSON del documento subyacente y comprobando la calificaci\u00f3n de la cerveza.<\/li>\n<li>En este caso, nuestro proceso se ejecuta eternamente, recibiendo continuamente nuevos mensajes a medida que se producen.<\/li>\n<\/ul>\n<h2>Aspectos a tener en cuenta<\/h2>\n<p>En nuestro ejemplo simplificado, lo que estamos almacenando en Couchbase es siempre un documento JSON. Pero este no tiene por qu\u00e9 ser el caso. As\u00ed que en tu aplicaci\u00f3n, probablemente tendr\u00e1s que construir algunas m\u00e1s inteligentes en ella para filtrar en base a las claves que te interesan, y no tratar de analizar todo como JSON. El contenido del evento DCP es un buffer de bytes, no es una cadena o un documento JSON. Esto es fiel a lo que Couchbase realmente almacena bajo el cap\u00f3.<\/p>\n<p>DCP tambi\u00e9n te informa de las mutaciones en momentos puntuales. Un detalle que hemos pasado un poco por alto es que, aunque las puntuaciones de algunas cervezas pueden superar el 4, esto no garantiza que la cerveza tenga esa puntuaci\u00f3n. <em>ahora mismo<\/em>s\u00f3lo una garant\u00eda de que era <em>una vez mutado<\/em>\u00a0a ese estado. Una construcci\u00f3n m\u00e1s sofisticada podr\u00eda tener esto en cuenta.<\/p>\n<p>Por \u00faltimo, ten en cuenta que realmente puede ser largo, dependiendo del tama\u00f1o y la velocidad de mutaci\u00f3n del cl\u00faster. As\u00ed que tal vez quieras echar un vistazo a <u><a href=\"https:\/\/github.com\/couchbase\/java-dcp-client#flow-control\" target=\"_blank\" rel=\"noopener noreferrer\">t\u00e9cnicas de control de flujo<\/a><\/u>\u00a0para que su cliente pueda seguir el flujo de acontecimientos.<\/p>\n<h2>\u00bfY ahora qu\u00e9?<\/h2>\n<p>Ahora que ya conoce los DCP, puede que le interese echar un vistazo a <u><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/connectors\/intro.html\" target=\"_blank\" rel=\"noopener noreferrer\">Conectores disponibles en Couchbase<\/a><\/u>que, en su mayor\u00eda, ya se basan en DCP, y le ofrecen una forma de aprovechar todo esto sin necesidad de codificaci\u00f3n.<\/p>\n<p>Otro tema que hay que estudiar es <u><a href=\"https:\/\/aws.amazon.com\/streaming-data\/\" target=\"_blank\" rel=\"noopener noreferrer\">sistemas de transmisi\u00f3n de datos<\/a><\/u>La mayor\u00eda de los proveedores de computaci\u00f3n en nube, como AWS, Google Compute Engine y otros, est\u00e1n haciendo cosas notables en este \u00e1mbito. La mayor\u00eda de los proveedores de computaci\u00f3n en la nube como AWS, Google Compute Engine y otros est\u00e1n haciendo algunas cosas notables en este espacio, y con DCP eres totalmente capaz de poner cualquier cosa que tengas en tu cl\u00faster de Couchbase en un flujo de datos que se puede conectar con cualquiera de estas potentes herramientas downstream.<\/p>\n<p><a target=\"_blank\" rel=\"noopener noreferrer\">[1]<\/a>\u00a0Es un poco m\u00e1s complicado, pero estoy simplificando y enlazando la arquitectura de almacenamiento para que puedas profundizar en el conocimiento de este tema.<\/p>\n<p><a href=\"https:\/\/www.couchbase.com\/blog\/es\/community\/community-writers-program\/\"><em>Este post forma parte del Programa de Escritura de la Comunidad Couchbase<\/em><\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>Escondido detr\u00e1s de un acr\u00f3nimo (DCP), Couchbase tiene un superpoder secreto. La mayor\u00eda de la gente piensa en las bases de datos como ubicaciones de almacenamiento de datos en un momento determinado en el tiempo. Pero con Database Change Protocol (DCP), un cl\u00faster Couchbase puede ser visto como un flujo continuo de cambios.<\/p>","protected":false},"author":53,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,9415],"tags":[10124,1976],"ppma_author":[9026],"class_list":["post-3980","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-xdcr","tag-amazon-web-services-aws","tag-dcp"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Database Change Protocol: History of DCP | Couchbase<\/title>\n<meta name=\"description\" content=\"Database Change Protocol (DCP) can be viewed as an ongoing stream of changes. Rewind history and replay what happened to the database from the beginning.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/es\/couchbases-history-everything-dcp\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Couchbase\u2019s History of Everything: DCP\" \/>\n<meta property=\"og:description\" content=\"Database Change Protocol (DCP) can be viewed as an ongoing stream of changes. Rewind history and replay what happened to the database from the beginning.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/couchbases-history-everything-dcp\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-09-07T23:42:02+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T03:46:36+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/09\/Simple-Small-Headshot-450x300-compressed.png\" \/>\n\t<meta property=\"og:image:width\" content=\"450\" \/>\n\t<meta property=\"og:image:height\" content=\"300\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Laura Czajkowski, Developer Community Manager, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Laura Czajkowski, Developer Community Manager, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/\"},\"author\":{\"name\":\"Laura Czajkowski, Developer Community Manager, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220\"},\"headline\":\"Couchbase\u2019s History of Everything: DCP\",\"datePublished\":\"2017-09-07T23:42:02+00:00\",\"dateModified\":\"2025-06-14T03:46:36+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/\"},\"wordCount\":1775,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"Amazon Web Services (AWS)\",\"DCP\"],\"articleSection\":[\"Couchbase Server\",\"Cross Data Center Replication (XDCR)\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/\",\"name\":\"Database Change Protocol: History of DCP | Couchbase\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2017-09-07T23:42:02+00:00\",\"dateModified\":\"2025-06-14T03:46:36+00:00\",\"description\":\"Database Change Protocol (DCP) can be viewed as an ongoing stream of changes. Rewind history and replay what happened to the database from the beginning.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Couchbase\u2019s History of Everything: DCP\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220\",\"name\":\"Laura Czajkowski, Developer Community Manager, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/9deb07d5daaa00220534c31768bc4409\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g\",\"caption\":\"Laura Czajkowski, Developer Community Manager, Couchbase\"},\"description\":\"Laura Czajkowski is the Snr. Developer Community Manager at Couchbase overseeing the community. She\u2019s responsible for our monthly developer newsletter.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/laura-czajkowski\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Database Change Protocol: History of DCP | Couchbase","description":"El Protocolo de Cambios de la Base de Datos (DCP) puede verse como un flujo continuo de cambios. Rebobina la historia y reproduce lo que le ha ocurrido a la base de datos desde el principio.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/es\/couchbases-history-everything-dcp\/","og_locale":"es_MX","og_type":"article","og_title":"Couchbase\u2019s History of Everything: DCP","og_description":"Database Change Protocol (DCP) can be viewed as an ongoing stream of changes. Rewind history and replay what happened to the database from the beginning.","og_url":"https:\/\/www.couchbase.com\/blog\/es\/couchbases-history-everything-dcp\/","og_site_name":"The Couchbase Blog","article_published_time":"2017-09-07T23:42:02+00:00","article_modified_time":"2025-06-14T03:46:36+00:00","og_image":[{"width":450,"height":300,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/09\/Simple-Small-Headshot-450x300-compressed.png","type":"image\/png"}],"author":"Laura Czajkowski, Developer Community Manager, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Laura Czajkowski, Developer Community Manager, Couchbase","Est. reading time":"9 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/"},"author":{"name":"Laura Czajkowski, Developer Community Manager, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220"},"headline":"Couchbase\u2019s History of Everything: DCP","datePublished":"2017-09-07T23:42:02+00:00","dateModified":"2025-06-14T03:46:36+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/"},"wordCount":1775,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["Amazon Web Services (AWS)","DCP"],"articleSection":["Couchbase Server","Cross Data Center Replication (XDCR)"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/","url":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/","name":"Database Change Protocol: History of DCP | Couchbase","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2017-09-07T23:42:02+00:00","dateModified":"2025-06-14T03:46:36+00:00","description":"El Protocolo de Cambios de la Base de Datos (DCP) puede verse como un flujo continuo de cambios. Rebobina la historia y reproduce lo que le ha ocurrido a la base de datos desde el principio.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/couchbases-history-everything-dcp\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Couchbase\u2019s History of Everything: DCP"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220","name":"Laura Czajkowski, Directora de la Comunidad de Desarrolladores, Couchbase","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/9deb07d5daaa00220534c31768bc4409","url":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","caption":"Laura Czajkowski, Developer Community Manager, Couchbase"},"description":"Laura Czajkowski es la Snr. Developer Community Manager en Couchbase supervisando la comunidad. Es responsable de nuestro bolet\u00edn mensual para desarrolladores.","url":"https:\/\/www.couchbase.com\/blog\/es\/author\/laura-czajkowski\/"}]}},"authors":[{"term_id":9026,"user_id":53,"is_guest":0,"slug":"laura-czajkowski","display_name":"Laura Czajkowski, Developer Community Manager, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","author_category":"","last_name":"Czajkowski","first_name":"Laura","job_title":"","user_url":"","description":"Laura Czajkowski es la Snr. Developer Community Manager en Couchbase supervisando la comunidad. Es responsable de nuestro bolet\u00edn mensual para desarrolladores."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/3980","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=3980"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/3980\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=3980"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=3980"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=3980"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=3980"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}