{"id":52541,"date":"2019-11-11T00:00:00","date_gmt":"2019-11-10T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost"},"modified":"2020-02-18T14:00:17","modified_gmt":"2020-02-18T11:00:17","slug":"rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost","status":"publish","type":"post","link":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost","title":{"rendered":"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/6557ce69c2b3070622feca8b3c228b09.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/471858\/\">el art\u00edculo anterior<\/a><\/noindex> Hemos revisado la agrupaci\u00f3n de RabbitMQ para garantizar la resistencia a fallos y la alta disponibilidad. Ahora profundizaremos en Apache Kafka.<\/p>\n<p>Aqu\u00ed, la unidad de replicaci\u00f3n es la partici\u00f3n. Cada tema tiene una o m\u00e1s particiones. En cada partici\u00f3n hay un l\u00edder con sus seguidores o sin ellos. Al crear un tema, se especifica el n\u00famero de particiones y el factor de replicaci\u00f3n. Un valor com\u00fan es 3, lo que significa tres r\u00e9plicas: un l\u00edder y dos seguidores.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/36deb6d506223c2ee2ec147d5c215789.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 1. Cuatro particiones distribuidas entre tres brokers<\/i><\/p>\n<p>Todas las solicitudes de lectura y escritura se dirigen al l\u00edder. Los seguidores env\u00edan peri\u00f3dicamente al l\u00edder solicitudes para obtener los \u00faltimos mensajes. Los consumidores nunca se dirigen a los seguidores, que existen \u00fanicamente por redundancia y resistencia a fallos.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/715c51d75cb45863cfad4b37e81b9a9a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h1>Fallo de partici\u00f3n<\/h1>\n<p>\nCuando un broker falla, a menudo se caen los l\u00edderes de varias particiones. En cada una de ellas, un seguidor de otro nodo se convierte en l\u00edder. Sin embargo, esto no siempre ocurre, ya que tambi\u00e9n influye el factor de sincronizaci\u00f3n: si hay seguidores sincronizados y, si no los hay, si se permite el cambio a una r\u00e9plica no sincronizada. Pero no compliquemos las cosas por ahora.<\/p>\n<p>El broker 3 se desconecta de la red, y se elige un nuevo l\u00edder para la partici\u00f3n 2 en el broker 2.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/b8cfce64cf6b848b0659de023f9d9b63.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 2. El broker 3 muere, y su seguidor en el broker 2 es elegido nuevo l\u00edder de la partici\u00f3n 2<\/i><\/p>\n<p>Luego, el broker 1 se desconecta y la partici\u00f3n 1 tambi\u00e9n pierde a su l\u00edder, cuyo rol pasa al broker 2.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/9f5409c723da7ff059b93f9b23e7d5f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 3. Solo queda un broker. Todos los l\u00edderes est\u00e1n en un solo broker con cero redundancia<\/i><\/p>\n<p>Cuando el broker 1 vuelve a la red, a\u00f1ade cuatro seguidores, proporcionando cierta redundancia a cada partici\u00f3n. Pero todos los l\u00edderes siguen estando en el broker 2.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/f9c8e42f51258b7fd7f6f35dc7b8cc3b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 4. Los l\u00edderes permanecen en el broker 2<\/i><\/p>\n<p>Cuando el broker 3 se levanta, volvemos a tener tres r\u00e9plicas en la partici\u00f3n. Pero todos los l\u00edderes siguen en el broker 2.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/9c8c02be4161f8468b5dbc1e3f6ecb3a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 5. Distribuci\u00f3n desequilibrada de los l\u00edderes tras la recuperaci\u00f3n de los brokers 1 y 3<\/i><\/p>\n<p>Kafka tiene una herramienta para realizar un reequilibrio de l\u00edderes de mejor calidad que RabbitMQ. En este \u00faltimo, se deb\u00eda utilizar un plugin externo o un script que modificaba las pol\u00edticas para migrar el nodo principal a costa de reducir la redundancia durante la migraci\u00f3n. Adem\u00e1s, para colas grandes, hab\u00eda que aceptar la indisponibilidad durante la sincronizaci\u00f3n.<\/p>\n<p>Kafka tiene el concepto de \"r\u00e9plicas preferidas\" para el papel de l\u00edder. Cuando se crean particiones de un tema, Kafka intenta distribuir los l\u00edderes de manera uniforme entre los nodos y marca a estos primeros l\u00edderes como preferidos. Con el tiempo, debido a reinicios de servidores, fallos y problemas de conectividad, los l\u00edderes pueden terminar en otros nodos, como se describi\u00f3 en el caso extremo anterior.<\/p>\n<p>Para solucionar esto, Kafka ofrece dos opciones:<\/p>\n<ul>\n<li>La opci\u00f3n <i>auto.leader.rebalance.enable=true<\/i> permite que el nodo controlador reasigne autom\u00e1ticamente los l\u00edderes de regreso a las r\u00e9plicas preferidas, restableciendo as\u00ed la distribuci\u00f3n uniforme.\n<\/li>\n<li>El administrador puede ejecutar el script <i>kafka-preferred-replica-election.sh<\/i> para reasignar manualmente.<\/li>\n<\/ul>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/831930b06809637018fecb6d7d5a558d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 6. R\u00e9plicas despu\u00e9s del rebalanceo<\/i><\/p>\n<p>Esta fue una versi\u00f3n simplificada de la falla, pero la realidad es m\u00e1s compleja, aunque no hay nada demasiado complicado aqu\u00ed. Todo se reduce a r\u00e9plicas sincronizadas (In-Sync Replicas, ISR).<\/p>\n<h1>R\u00e9plicas Sincronizadas (ISR)<\/h1>\n<p>\nISR es un conjunto de r\u00e9plicas de una partici\u00f3n que se considera \"sincronizada\" (in-sync). Aqu\u00ed hay un l\u00edder, y puede que no haya seguidores. Un seguidor se considera sincronizado si ha hecho copias exactas de todos los mensajes del l\u00edder antes de que expire el intervalo <i>replica.lag.time.max.ms<\/i>.<\/p>\n<p>Un seguidor se elimina del conjunto ISR si:<\/p>\n<ul>\n<li>no ha realizado una solicitud de recuperaci\u00f3n dentro del intervalo <i>replica.lag.time.max.ms<\/i> (se considera muerto)\n<\/li>\n<li>no se actualiz\u00f3 a tiempo dentro del intervalo <i>replica.lag.time.max.ms<\/i> (se considera lento)<\/li>\n<\/ul>\n<p>\nLos seguidores realizan solicitudes de recuperaci\u00f3n en el intervalo <i>replica.fetch.wait.max.ms<\/i>, que por defecto es de 500 ms.<\/p>\n<p>Para explicar claramente el prop\u00f3sito del ISR, es necesario observar las confirmaciones del productor y algunos escenarios de falla. Los productores pueden elegir cu\u00e1ndo el corredor env\u00eda una confirmaci\u00f3n:<\/p>\n<ul>\n<li>acks=0, la confirmaci\u00f3n no se env\u00eda\n<\/li>\n<li>acks=1, la confirmaci\u00f3n se env\u00eda despu\u00e9s de que el l\u00edder haya escrito el mensaje en su registro local\n<\/li>\n<li>acks=all, la confirmaci\u00f3n se env\u00eda despu\u00e9s de que todas las r\u00e9plicas en el ISR hayan escrito el mensaje en sus registros locales<\/li>\n<\/ul>\n<p>\nEn la terminolog\u00eda de Kafka, si el ISR ha mantenido el mensaje, se produce su \u00abcommit\u00bb. Acks=all es la opci\u00f3n m\u00e1s segura, pero tambi\u00e9n introduce una demora adicional. Vamos a analizar dos ejemplos de fallos y c\u00f3mo las diferentes opciones de 'acks' interact\u00faan con el concepto de ISR.<\/p>\n<h3>Acks=1 y ISR<\/h3>\n<p>\nEn este ejemplo, veremos que si el l\u00edder no espera la confirmaci\u00f3n de cada mensaje de todos los seguidores, podr\u00eda haber p\u00e9rdida de datos en caso de fallo del l\u00edder. El paso a un seguidor no sincronizado puede permitirse o denegarse mediante la configuraci\u00f3n. <i>unclean.leader.election.enable<\/i>.<\/p>\n<p>En este ejemplo, el productor tiene el valor acks=1. La partici\u00f3n est\u00e1 distribuida entre los tres brokers. El broker 3 est\u00e1 retrasado; se sincroniz\u00f3 con el l\u00edder hace ocho segundos y ahora tiene un retraso de 7456 mensajes. El broker 1 solo tiene un segundo de retraso. Nuestro productor env\u00eda un mensaje y r\u00e1pidamente recibe un ack, sin sobrecarga sobre seguidores lentos o ca\u00eddos que el l\u00edder no est\u00e1 esperando.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/f194e6309b732b772574392eff482a8b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 7. ISR con tres r\u00e9plicas<\/i><\/p>\n<p>El broker 2 falla, y el productor recibe un error de conexi\u00f3n. Despu\u00e9s del cambio de liderazgo al broker 1, perdemos 123 mensajes. El seguidor en el broker 1 estaba en ISR, pero no se hab\u00eda sincronizado completamente con el l\u00edder cuando este fall\u00f3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/367f219daebafefe585059f67fdedf6f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 8. Se pierden mensajes en caso de fallo<\/i><\/p>\n<p>En la configuraci\u00f3n <i>bootstrap.servers<\/i> el productor enumera varios brokers y puede preguntar a otro broker qui\u00e9n se convirti\u00f3 en el nuevo l\u00edder de la partici\u00f3n. Luego establece una conexi\u00f3n con el broker 1 y contin\u00faa enviando mensajes.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/ba45c51f4ce1f63f10b2fa0e1487b223.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 9. La producci\u00f3n de mensajes se reanuda despu\u00e9s de un breve descanso<\/i><\/p>\n<p>El broker 3 est\u00e1 a\u00fan m\u00e1s retrasado. Hace solicitudes de recuperaci\u00f3n, pero no puede sincronizarse. Esto podr\u00eda deberse a una conexi\u00f3n de red lenta entre los brokers, problemas de almacenamiento, etc. Sale de ISR. \u00a1Ahora ISR consiste en una \u00fanica r\u00e9plica: el l\u00edder! El productor sigue enviando mensajes y recibiendo confirmaciones.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/592c74632e3a8d80c2b4fc15bde5d401.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 10. El seguidor en el broker 3 es eliminado de ISR<\/i><\/p>\n<p>El broker 1 falla y el liderazgo se transfiere al broker 3 con una p\u00e9rdida de 15286 mensajes. El productor recibe un mensaje de error de conexi\u00f3n. El paso al l\u00edder fuera de ISR fue posible solo por la configuraci\u00f3n <i>unclean.leader.election.enable=true<\/i>. Si se establece en <i>false<\/i>, entonces el cambio no habr\u00eda ocurrido y todas las solicitudes de lectura y escritura habr\u00edan sido rechazadas. En este caso, esperamos el regreso del broker 1 con sus datos intactos en la r\u00e9plica, que volver\u00e1 a asumir el liderazgo.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/30f01ca715ccc194890ae061a3ef7396.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 11. El broker 1 falla. Se pierde una gran cantidad de mensajes en caso de fallo.<\/i><\/p>\n<p>El productor establece conexi\u00f3n con el \u00faltimo corredor y ve que ahora es el l\u00edder de la secci\u00f3n. Comienza a enviar mensajes al corredor 3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/986532d9b22b6514b6039c8460b1beb4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 12. Despu\u00e9s de una breve pausa, los mensajes se env\u00edan nuevamente a la secci\u00f3n 0.<\/i><\/p>\n<p>Hemos visto que, adem\u00e1s de las breves interrupciones para establecer nuevas conexiones y buscar un nuevo l\u00edder, el productor envi\u00f3 constantemente mensajes. Esta configuraci\u00f3n asegura disponibilidad a expensas de la consistencia (seguridad de los datos). Kafka perdi\u00f3 miles de mensajes, pero sigui\u00f3 aceptando nuevas entradas.<\/p>\n<h3>Acks=all e ISR.<\/h3>\n<p>\nRepitamos este escenario una vez m\u00e1s, pero con <i>acks=all.<\/i>La latencia del corredor 3 es de alrededor de cuatro segundos. El productor env\u00eda un mensaje con <i>acks=all.<\/i>, y ahora no recibe una respuesta r\u00e1pida. El l\u00edder espera a que el mensaje sea guardado por todas las r\u00e9plicas en ISR.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/95b1abdc92e699f7bc41ebab249a2e08.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 13. ISR con tres r\u00e9plicas. Una funciona lentamente, lo que provoca un retraso en la escritura.<\/i><\/p>\n<p>Despu\u00e9s de cuatro segundos de latencia adicional, el corredor 2 env\u00eda ack. Todas las r\u00e9plicas ahora est\u00e1n completamente actualizadas.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/64356dc8d2641a3e22947126dd047f39.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 14. Todas las r\u00e9plicas guardan mensajes y se env\u00eda ack.<\/i><\/p>\n<p>El corredor 3 ahora se retrasa a\u00fan m\u00e1s y se elimina de ISR. La latencia se reduce significativamente, ya que no quedan r\u00e9plicas lentas en ISR. El corredor 2 ahora solo espera al corredor 1, que tiene un retraso promedio de 500 ms.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/5d3bd67dc53cb868fa40b358ed483a1d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 15. La r\u00e9plica en el corredor 3 es eliminada de ISR.<\/i><\/p>\n<p>Luego, el corredor 2 falla y el liderazgo se transfiere al corredor 1 sin p\u00e9rdida de mensajes.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/e3f0417aa7714ea5eae8a8e8d61662bd.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 16. El corredor 2 falla.<\/i><\/p>\n<p>El productor encuentra un nuevo l\u00edder y comienza a enviarle mensajes. La latencia disminuye a\u00fan m\u00e1s, ya que ahora ISR consta de una sola r\u00e9plica. Por lo tanto, la opci\u00f3n <i>acks=all.<\/i> no a\u00f1ade redundancia.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/fec9aae9977757d5f61c2909ceae0536.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 17. La r\u00e9plica en el corredor 1 asume el liderazgo sin p\u00e9rdida de mensajes.<\/i><\/p>\n<p>Luego, el corredor 1 falla y el liderazgo se transfiere al corredor 3 con una p\u00e9rdida de 14238 mensajes.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/730b3951fb75ab3a782fc6d064615212.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 18. El corredor 1 muere, y la transferencia de liderazgo con la configuraci\u00f3n unclean causa una gran p\u00e9rdida de datos.<\/i><\/p>\n<p>Podr\u00edamos no haber establecido la opci\u00f3n <i>unclean.leader.election.enable<\/i> en <i>true<\/i>. Por defecto, es igual a <i>false<\/i>. La configuraci\u00f3n <i>acks=all.<\/i> con <i>unclean.leader.election.enable=true<\/i> asegura disponibilidad con cierta seguridad adicional de los datos. Pero, como pueden ver, todav\u00eda podemos perder mensajes.<\/p>\n<p>\u00bfY si queremos aumentar la seguridad de los datos? Se puede establecer <i>unclean.leader.election.enable = false.<\/i>, pero esto no necesariamente nos proteger\u00e1 de la p\u00e9rdida de datos. Si el l\u00edder falla de manera cr\u00edtica y pierde los datos, los mensajes siguen estando perdidos, adem\u00e1s de que se pierde la disponibilidad hasta que el administrador restaure la situaci\u00f3n.<\/p>\n<p>Es mejor garantizar la redundancia de todos los mensajes, o de lo contrario, renunciar a la grabaci\u00f3n. De esta manera, al menos desde el punto de vista del broker, la p\u00e9rdida de datos solo puede ocurrir en caso de dos o m\u00e1s fallos simult\u00e1neos.<\/p>\n<h3>Acks=all, min.insync.replicas e ISR<\/h3>\n<p>\nCon la configuraci\u00f3n del tema <i>min.insync.replicas<\/i> aumentamos el nivel de seguridad de los datos. Volvamos a pasar por la \u00faltima parte del escenario anterior, pero esta vez con <i>min.insync.replicas=2<\/i>.<\/p>\n<p>As\u00ed que el broker 2 tiene un l\u00edder de r\u00e9plica, y el seguidor en el broker 3 est\u00e1 eliminado del ISR.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/5831463293f1837d3232756894e97162.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 19. ISR de dos r\u00e9plicas<\/i><\/p>\n<p>El broker 2 falla, y el liderazgo pasa al broker 1 sin p\u00e9rdida de mensajes. Pero ahora el ISR consta solo de una r\u00e9plica. Esto no cumple con el n\u00famero m\u00ednimo para grabaciones, y por lo tanto, el broker responde con un error en el intento de grabaci\u00f3n. <i>NotEnoughReplicas<\/i>.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/6b2ee477f4c33ec84f3068b792814e5d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 20. El n\u00famero de ISR es uno menos de lo indicado en min.insync.replicas<\/i><\/p>\n<p>Esta configuraci\u00f3n sacrifica la disponibilidad por la coherencia. Antes de confirmar el mensaje, garantizamos que se graba en al menos dos r\u00e9plicas. Esto da al productor mucha m\u00e1s confianza. Aqu\u00ed la p\u00e9rdida de mensajes solo es posible con el fallo simult\u00e1neo de dos r\u00e9plicas en un intervalo corto, mientras el mensaje no ha sido replicado en otro seguidor, lo cual es poco probable. Pero si eres un paranoico extremo, puedes establecer un factor de replicaci\u00f3n de 5, y <i>min.insync.replicas<\/i> as\u00ed como 3. Aqu\u00ed deben fallar simult\u00e1neamente tres brokers para perder la grabaci\u00f3n. Por supuesto, por tal fiabilidad pagar\u00e1s con un retraso adicional.<\/p>\n<h1>Cuando la disponibilidad es necesaria para la seguridad de los datos<\/h1>\n<p>\nComo en <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/471858\/\">en el caso de RabbitMQ<\/a><\/noindex>, a veces la disponibilidad es necesaria para la seguridad de los datos. Debes pensar en lo siguiente:<\/p>\n<ul>\n<li>\u00bfPuede el publicador simplemente devolver un error, y el servicio o usuario superior intentar\u00e1 de nuevo m\u00e1s tarde?\n<\/li>\n<li>\u00bfPuede el publicador guardar el mensaje localmente o en una base de datos para volver a intentarlo m\u00e1s tarde?<\/li>\n<\/ul>\n<p>\nSi la respuesta es negativa, entonces la optimizaci\u00f3n de la disponibilidad aumenta la seguridad de los datos. Perder\u00e1s menos datos si eliges disponibilidad en lugar de renunciar a la grabaci\u00f3n. As\u00ed que todo se reduce a encontrar un equilibrio, y la decisi\u00f3n depende de la situaci\u00f3n espec\u00edfica.<\/p>\n<h1>El sentido de ISR<\/h1>\n<p>\nEl conjunto ISR permite seleccionar el equilibrio \u00f3ptimo entre la seguridad de los datos y la latencia. Por ejemplo, garantiza la disponibilidad en caso de fallos en la mayor\u00eda de las r\u00e9plicas, minimizando el impacto de r\u00e9plicas muertas o lentas en t\u00e9rminos de latencia.<\/p>\n<p>Nosotros elegimos el valor <i>replica.lag.time.max.ms<\/i> de acuerdo con nuestras necesidades. Esencialmente, este par\u00e1metro significa qu\u00e9 latencia estamos dispuestos a aceptar al <i>acks=all.<\/i>. El valor predeterminado es de diez segundos. Si esto es demasiado largo para usted, puede reducirlo. Entonces, la frecuencia de cambios en el ISR aumentar\u00e1, ya que los seguidores ser\u00e1n eliminados y agregados con m\u00e1s frecuencia.<\/p>\n<p>En RabbitMQ, simplemente hay un conjunto de espejos que deben ser replicados. Los espejos lentos introducen latencia adicional, y la respuesta de espejos muertos puede tardar hasta el tiempo de vida de los paquetes que revisan la disponibilidad de cada nodo (net tick). ISR es una forma interesante de evitar estos problemas de latencia aumentada. Pero corremos el riesgo de perder redundancia, ya que el ISR puede reducirse solo al l\u00edder. Para evitar este riesgo, utilice la configuraci\u00f3n <i>min.insync.replicas<\/i>.<\/p>\n<h1>Garant\u00eda de conexi\u00f3n de clientes<\/h1>\n<p>\nEn la configuraci\u00f3n <i>bootstrap.servers<\/i> del productor y el consumidor, puede especificar varios brokers para la conexi\u00f3n de clientes. La idea es que, si un nodo se desconecta, quedan varios de reserva con los que el cliente puede abrir una conexi\u00f3n. No son necesariamente los l\u00edderes de particiones, sino simplemente plataformas para la carga inicial. El cliente puede preguntarles en qu\u00e9 nodo se encuentra el l\u00edder de partici\u00f3n para lectura\/escritura.<\/p>\n<p>En RabbitMQ, los clientes pueden conectarse a cualquier nodo, y el enrutamiento interno env\u00eda la solicitud a donde debe. Esto significa que puede colocar un equilibrador de carga antes de RabbitMQ. Kafka requiere que los clientes se conecten al nodo donde se encuentra el l\u00edder de la partici\u00f3n correspondiente. En tal situaci\u00f3n, no se puede instalar un equilibrador de carga. La lista <i>bootstrap.servers<\/i> es cr\u00edtica para que los clientes puedan acceder a los nodos necesarios y encontrarlos despu\u00e9s de un fallo.<\/p>\n<h1>Arquitectura de consenso de Kafka<\/h1>\n<p>\nHasta ahora, no hemos considerado c\u00f3mo el cl\u00faster se entera de la ca\u00edda de un broker y c\u00f3mo se elige un nuevo l\u00edder. Para entender c\u00f3mo Kafka maneja las particiones de red, primero es necesario comprender la arquitectura de consenso.<\/p>\n<p>Cada cl\u00faster de Kafka se despliega junto con un cl\u00faster de Zookeeper, un servicio de consenso distribuido que permite a la sistema alcanzar un consenso en un estado espec\u00edfico, priorizando la consistencia sobre la disponibilidad. Para la autorizaci\u00f3n de operaciones de lectura y escritura se requiere el consentimiento de la mayor\u00eda de los nodos de Zookeeper.<\/p>\n<p>Zookeeper almacena el estado del cl\u00faster:<\/p>\n<ul>\n<li>Lista de temas, particiones, configuraci\u00f3n, r\u00e9plicas l\u00edderes actuales, r\u00e9plicas preferidas.\n<\/li>\n<li>Miembros del cl\u00faster. Cada corredor env\u00eda un ping al cl\u00faster de Zookeeper. Si no recibe un ping en un periodo de tiempo establecido, Zookeeper registra al corredor como no disponible.\n<\/li>\n<li>Selecci\u00f3n de nodos principales y de respaldo para el controlador.<\/li>\n<\/ul>\n<p>\nEl nodo controlador es uno de los corredores de Kafka que es responsable de la elecci\u00f3n de l\u00edderes de r\u00e9plicas. Zookeeper env\u00eda notificaciones al controlador sobre el estado de membres\u00eda en el cl\u00faster y cambios en los temas, y el controlador debe actuar de acuerdo a esos cambios.<\/p>\n<p>Por ejemplo, tomemos un nuevo tema con diez particiones y un factor de replicaci\u00f3n de 3. El controlador debe elegir un l\u00edder para cada partici\u00f3n, tratando de distribuir los l\u00edderes de forma \u00f3ptima entre los corredores. <\/p>\n<p>Para cada partici\u00f3n, el controlador:<\/p>\n<ul>\n<li>actualiza la informaci\u00f3n en Zookeeper sobre ISR y el l\u00edder;\n<\/li>\n<li>env\u00eda el comando LeaderAndISRCommand a cada corredor que aloja una r\u00e9plica de esta partici\u00f3n, informando a los corredores sobre el ISR y el l\u00edder.<\/li>\n<\/ul>\n<p>\nCuando un corredor l\u00edder falla, Zookeeper env\u00eda una notificaci\u00f3n al controlador, y este elige un nuevo l\u00edder. De nuevo, el controlador primero actualiza Zookeeper y luego env\u00eda un comando a cada corredor, notific\u00e1ndoles sobre el cambio de liderazgo.<\/p>\n<p>Cada l\u00edder es responsable del conjunto de ISR. La configuraci\u00f3n <i>replica.lag.time.max.ms<\/i> determina qui\u00e9n entrar\u00e1. Cuando cambia el ISR, el l\u00edder env\u00eda nueva informaci\u00f3n a Zookeeper.<\/p>\n<p>Zookeeper siempre est\u00e1 informado de cualquier cambio, de modo que en caso de fallo, la transici\u00f3n de liderazgo se realice sin problemas hacia el nuevo l\u00edder.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/3adb1d204b28e3ed85bef3530fa2b738.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 21. Consenso de Kafka<\/i><\/p>\n<h1>Protocolo de replicaci\u00f3n<\/h1>\n<p>\nComprender los detalles de la replicaci\u00f3n ayuda a entender mejor los potenciales escenarios de p\u00e9rdida de datos.<\/p>\n<h3>Solicitudes de acceso, Log End Offset (LEO) y Highwater Mark (HW)<\/h3>\n<p>\nHemos considerado que los seguidores env\u00edan peri\u00f3dicamente solicitudes de extracci\u00f3n (fetch) al l\u00edder. El intervalo por defecto es de 500 ms. Esto difiere de RabbitMQ en que en RabbitMQ la replicaci\u00f3n es iniciada no por el espejo de la cola, sino por el maestro. El maestro env\u00eda los cambios a los espejos.<\/p>\n<p>El l\u00edder y todos los seguidores mantienen el desplazamiento del final del registro (Log End Offset, LEO) y la marca de alto nivel (Highwater, HW). La marca LEO almacena el desplazamiento del \u00faltimo mensaje en la r\u00e9plica local, mientras que HW almacena el desplazamiento del \u00faltimo compromiso. Recuerde que para el estado \"comprometido\" el mensaje debe estar almacenado en todas las r\u00e9plicas ISR. Esto significa que LEO generalmente est\u00e1 un poco por delante de HW.<\/p>\n<p>Cuando el l\u00edder recibe un mensaje, lo almacena localmente. El seguidor realiza una solicitud de extracci\u00f3n, enviando su LEO. Luego, el l\u00edder env\u00eda un paquete de mensajes, comenzando desde este LEO, y tambi\u00e9n transmite el HW actual. Cuando el l\u00edder recibe informaci\u00f3n de que todas las r\u00e9plicas han almacenado el mensaje con el desplazamiento especificado, mueve la marca HW. Solo el l\u00edder puede mover el HW, y as\u00ed todos los seguidores conocen el valor actual en las respuestas a sus solicitudes. Esto significa que los seguidores pueden quedarse atr\u00e1s del l\u00edder tanto en mensajes como en el conocimiento de HW. Los consumidores reciben mensajes solo hasta el HW actual.<\/p>\n<p>Tenga en cuenta que \"persistido\" (persisted) significa almacenado en memoria, no en disco. Por razones de rendimiento, Kafka realiza la sincronizaci\u00f3n en disco a intervalos espec\u00edficos. RabbitMQ tambi\u00e9n tiene este intervalo, pero solo enviar\u00e1 una confirmaci\u00f3n al publicador despu\u00e9s de que el maestro y todos los espejos hayan almacenado el mensaje en disco. Los desarrolladores de Kafka, por razones de rendimiento, decidieron enviar el ack tan pronto como el mensaje est\u00e1 almacenado en memoria. Kafka apuesta a que la redundancia compensar\u00e1 el riesgo de mantener confirmaciones de mensajes solo en memoria a corto plazo.<\/p>\n<h1>Fallo del l\u00edder<\/h1>\n<p>\nCuando el l\u00edder falla, Zookeeper notifica al controlador, y este elige un nuevo r\u00e9plica l\u00edder. El nuevo l\u00edder establece una nueva marca HW de acuerdo con su LEO. Luego, los seguidores reciben la informaci\u00f3n sobre el nuevo l\u00edder. Dependiendo de la versi\u00f3n de Kafka, el seguidor elegir\u00e1 uno de los dos escenarios:<\/p>\n<ol>\n<li>Truncar\u00e1 el registro local hasta el conocido HW y enviar\u00e1 al nuevo l\u00edder una solicitud de mensajes despu\u00e9s de esta marca.\n<\/li>\n<li>Enviar\u00e1 una solicitud al l\u00edder para conocer el HW en el momento de su elecci\u00f3n, y luego truncar\u00e1 el registro hasta ese desplazamiento. Luego comenzar\u00e1 a realizar solicitudes peri\u00f3dicas de muestreo, comenzando desde este desplazamiento.<\/li>\n<\/ol>\n<p>\nPuede que el seguidor necesite truncar el registro por las siguientes razones:<\/p>\n<ul>\n<li>Cuando una falla ocurre en el l\u00edder, el primer seguidor del conjunto ISR, registrado en Zookeeper, gana las elecciones y se convierte en l\u00edder. Todos los seguidores en ISR, aunque se consideran \"sincronizados\", pueden no haber recibido del antiguo l\u00edder copias de todos los mensajes. Es posible que el seguidor electo no tenga la copia m\u00e1s actual. Kafka garantiza que no hay discrepancias entre r\u00e9plicas. Por lo tanto, para evitar discrepancias, cada seguidor debe truncar su registro hasta el valor HW del nuevo l\u00edder en el momento de su elecci\u00f3n. Esta es otra raz\u00f3n por la cual la configuraci\u00f3n <i>acks=all.<\/i> es tan importante para la coherencia.\n<\/li>\n<li>Los mensajes se graban peri\u00f3dicamente en disco. Si todos los nodos del cl\u00faster fallan al mismo tiempo, en los discos se guardar\u00e1n r\u00e9plicas con distintos desplazamientos. Es posible que cuando los corredores regresen a la red, el nuevo l\u00edder que sea elegido se quede atr\u00e1s de sus seguidores, porque se guard\u00f3 en disco antes que los dem\u00e1s.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Reconexi\u00f3n al cl\u00faster<\/h3>\n<p>\nAl reconectarse al cl\u00faster, las r\u00e9plicas se manejan de la misma manera que en un fallo del l\u00edder: verifican la r\u00e9plica del l\u00edder y truncar\u00e1n su registro hasta su HW (en el momento de la elecci\u00f3n). En comparaci\u00f3n, RabbitMQ considera los nodos reconectados como completamente nuevos. En ambos casos, el corredor descarta cualquier estado existente. Si se utiliza una sincronizaci\u00f3n autom\u00e1tica, el maestro debe replicar absolutamente todo el contenido actual en el nuevo espejo de manera \"y que espere el mundo entero\". Durante esta operaci\u00f3n, el maestro no acepta ninguna operaci\u00f3n de lectura o escritura. Este enfoque crea problemas en grandes colas.<\/p>\n<p>Kafka es un registro distribuido y, en general, almacena m\u00e1s mensajes que una cola de RabbitMQ, donde los datos se eliminan de la cola despu\u00e9s de ser le\u00eddos. Las colas activas deben mantenerse relativamente peque\u00f1as. Pero Kafka es un registro con su propia pol\u00edtica de almacenamiento, que puede establecer un l\u00edmite de d\u00edas o semanas. El enfoque de bloqueo de la cola y la sincronizaci\u00f3n completa es absolutamente inaceptable para un registro distribuido. En su lugar, los seguidores de Kafka simplemente recortan su registro hasta el l\u00edder HW (en el momento de su elecci\u00f3n) si su copia supera al l\u00edder. En el caso m\u00e1s probable, cuando el seguidor est\u00e1 retrasado, simplemente comienza a hacer solicitudes de recuperaci\u00f3n, comenzando desde su LEO actual.<\/p>\n<p>Los seguidores nuevos o reintroducidos comienzan fuera del ISR y no participan en los commits. Simplemente trabajan junto al grupo, recibiendo mensajes tan r\u00e1pido como pueden hasta que alcanzan al l\u00edder y entran en el ISR. Aqu\u00ed no hay bloqueo y no es necesario desechar todos sus datos.<\/p>\n<h1>Violaci\u00f3n de la coherencia<\/h1>\n<p>\nKafka tiene m\u00e1s componentes que RabbitMQ, por lo que hay un conjunto de comportamientos m\u00e1s complejo cuando se rompe la conectividad en el cl\u00faster. Pero Kafka fue dise\u00f1ado originalmente para cl\u00fasteres, as\u00ed que las soluciones est\u00e1n muy bien pensadas.<\/p>\n<p>A continuaci\u00f3n se presentan algunos escenarios de ruptura de conectividad:<\/p>\n<ul>\n<li>Escenario 1. El seguidor no ve al l\u00edder, pero a\u00fan ve a Zookeeper.\n<\/li>\n<li>Escenario 2. El l\u00edder no ve a ning\u00fan seguidor, pero a\u00fan ve a Zookeeper.\n<\/li>\n<li>Escenario 3. El seguidor ve al l\u00edder, pero no ve a Zookeeper.\n<\/li>\n<li>Escenario 4. El l\u00edder ve a los seguidores, pero no ve a Zookeeper.\n<\/li>\n<li>Escenario 5. El seguidor est\u00e1 completamente aislado tanto de otros nodos de Kafka como de Zookeeper.\n<\/li>\n<li>Escenario 6. El l\u00edder est\u00e1 completamente aislado tanto de otros nodos de Kafka como de Zookeeper.\n<\/li>\n<li>Escenario 7. El nodo controlador de Kafka no ve a otro nodo de Kafka.\n<\/li>\n<li>Escenario 8. El controlador de Kafka no ve a Zookeeper.<\/li>\n<\/ul>\n<p>\nSe prev\u00e9 un comportamiento espec\u00edfico para cada escenario.<\/p>\n<h3>Escenario 1. El seguidor no ve al l\u00edder, pero a\u00fan ve a Zookeeper.<\/h3>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/5f51ae679933b2b5a69e21831465d121.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 22. Escenario 1. ISR de tres r\u00e9plicas.<\/i><\/p>\n<p>La ruptura de conectividad a\u00edsla al corredor 3 de los corredores 1 y 2, pero no de Zookeeper. El corredor 3 ya no puede enviar solicitudes de recuperaci\u00f3n. Con el tiempo. <i>replica.lag.time.max.ms<\/i> se elimina del ISR y no participa en los commits de mensajes. Una vez que se restaura la conectividad, reanuda las solicitudes de extracci\u00f3n y se une al ISR cuando alcanza al l\u00edder. Zookeeper continuar\u00e1 recibiendo pings y considerar\u00e1 que el corredor est\u00e1 vivo y saludable.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/976b7ff080ee6a6d76a165f614f40e95.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 23. Escenario 1. El corredor se elimina del ISR si no recibe una solicitud de extracci\u00f3n durante el intervalo replica.lag.time.max.ms<\/i><\/p>\n<p>No hay ninguna separaci\u00f3n l\u00f3gica (split-brain) o suspensi\u00f3n del nodo, como en RabbitMQ. En su lugar, se reduce la redundancia. <\/p>\n<h3>Escenario 2. El l\u00edder no ve a ning\u00fan seguidor, pero todav\u00eda ve a Zookeeper<\/h3>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/ff6aaa053d73e8b7c97111979bcf97aa.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 24. Escenario 2. L\u00edder y dos seguidores<\/i><\/p>\n<p>La interrupci\u00f3n de la conectividad de red separa al l\u00edder de los seguidores, pero el corredor todav\u00eda ve a Zookeeper. Al igual que en el primer escenario, el ISR se comprime, pero esta vez solo hasta el l\u00edder, ya que todos los seguidores dejan de enviar solicitudes de extracci\u00f3n. Nuevamente, no hay ninguna separaci\u00f3n l\u00f3gica. En su lugar, ocurre una p\u00e9rdida de redundancia para nuevos mensajes, hasta que se restaura la conectividad. Zookeeper contin\u00faa recibiendo pings y considera que el corredor est\u00e1 vivo y saludable.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/3c69e8327da241407f76719fc022c37a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 25. Escenario 2. El ISR se ha comprimido solo hasta el l\u00edder<\/i><\/p>\n<h3>Escenario 3. El seguidor ve al l\u00edder, pero no ve a Zookeeper<\/h3>\n<p>\nEl seguidor se separa de Zookeeper, pero no del corredor con el l\u00edder. Como resultado, el seguidor contin\u00faa haciendo solicitudes de extracci\u00f3n y siendo miembro del ISR. Zookeeper ya no recibe pings y registra la ca\u00edda del corredor, pero dado que solo es un seguidor, no hay consecuencias despu\u00e9s de la recuperaci\u00f3n.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/1183bcfe45a3225ae3ef1a0651f61350.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 26. Escenario 3. El seguidor contin\u00faa enviando al l\u00edder solicitudes de extracci\u00f3n<\/i><\/p>\n<h3>Escenario 4. El l\u00edder ve a los seguidores, pero no ve a Zookeeper<\/h3>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/b3bf27fcb0eb806b27ad00f098e50a26.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 27. Escenario 4. L\u00edder y dos seguidores<\/i><\/p>\n<p>El l\u00edder est\u00e1 separado de Zookeeper, pero no de los corredores con seguidores. <\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/82d9f2e5868566678befc414d1885bfd.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 28. Escenario 4. El l\u00edder est\u00e1 aislado de Zookeeper<\/i><\/p>\n<p>Despu\u00e9s de un tiempo, Zookeeper registrar\u00e1 la ca\u00edda del corredor y notificar\u00e1 al controlador. Este elegir\u00e1 un nuevo l\u00edder entre los seguidores. Sin embargo, el l\u00edder original seguir\u00e1 creyendo que es el l\u00edder y continuar\u00e1 aceptando registros con <i>acks=1<\/i>. Los seguidores ya no le env\u00edan solicitudes de extracci\u00f3n, por lo que \u00e9l los considerar\u00e1 muertos y tratar\u00e1 de comprimir el ISR hasta s\u00ed mismo. Pero como no tiene conexi\u00f3n a Zookeeper, no podr\u00e1 hacerlo y en ese momento dejar\u00e1 de aceptar registros. <\/p>\n<p>Mensajes <i>acks=all.<\/i> no recibir\u00e1n confirmaciones porque primero el ISR incluye todas las r\u00e9plicas, y hasta que no se reciban los mensajes. Cuando el l\u00edder original intente eliminarlas del ISR, no podr\u00e1 hacerlo y dejar\u00e1 de aceptar cualquier mensaje.<\/p>\n<p>Los clientes pronto notan el cambio de l\u00edder y comienzan a enviar registros al nuevo servidor. Una vez que la red se restablece, el l\u00edder original ve que ya no es l\u00edder y recorta su registro al valor de HW que ten\u00eda el nuevo l\u00edder en el momento de la falla, para evitar la divergencia de registros. Luego comenzar\u00e1 a enviar solicitudes de recuperaci\u00f3n al nuevo l\u00edder. Se perder\u00e1n todos los registros del l\u00edder original que no fueron replicados al nuevo l\u00edder. Es decir, se perder\u00e1n los mensajes que no fueron confirmados por el l\u00edder original en esos pocos segundos en los que funcionaron dos l\u00edderes.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/d88d6f33c13dccb814c0f206ec72512b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 29. Escenario 4. El l\u00edder en el corredor 1 se convierte en seguidor tras la recuperaci\u00f3n de la red<\/i><\/p>\n<h3>Escenario 5. El seguidor est\u00e1 completamente aislado tanto de otros nodos de Kafka como de Zookeeper<\/h3>\n<p>\nEl seguidor est\u00e1 completamente aislado de otros nodos de Kafka y de Zookeeper. Simplemente se elimina del ISR hasta que la red se restablezca, y luego alcanza a los dem\u00e1s.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/b092607f777014fd945f18734dd7f4e7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 30. Escenario 5. El seguidor aislado se elimina del ISR<\/i><\/p>\n<h3>Escenario 6. El l\u00edder est\u00e1 completamente aislado de otros nodos de Kafka y de Zookeeper<\/h3>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/bb808d534dbf65748eb0b481f86b4926.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 31. Escenario 6. L\u00edder y dos seguidores<\/i><\/p>\n<p>El l\u00edder est\u00e1 completamente aislado de sus seguidores, del controlador y de Zookeeper. Durante un corto periodo, continuar\u00e1 aceptando registros de <i>acks=1<\/i>.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/6fda78bcd26ef6b916579d447e9fb1f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 32. Escenario 6. Aislamiento del l\u00edder de otros nodos de Kafka y Zookeeper<\/i><\/p>\n<p>No recibiendo solicitudes al expirar <i>replica.lag.time.max.ms<\/i>, intentar\u00e1 reducir el ISR a s\u00ed mismo, pero no podr\u00e1 hacerlo, ya que no hay conexi\u00f3n con Zookeeper, y entonces dejar\u00e1 de aceptar registros. <\/p>\n<p>Mientras tanto, Zookeeper marcar\u00e1 al corredor aislado como muerto, y el controlador elegir\u00e1 un nuevo l\u00edder.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/73d611a411fc64d835af2c714e9eba0a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 33. Escenario 6. Dos l\u00edderes<\/i><\/p>\n<p>El l\u00edder original puede aceptar registros durante unos segundos, pero luego deja de aceptar cualquier mensaje. Los clientes se actualizan cada 60 segundos con los \u00faltimos metadatos. Ser\u00e1n informados sobre el cambio de l\u00edder y comenzar\u00e1n a enviar registros al nuevo l\u00edder.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/ae99380c8a84fac15f440b699b9c552b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 34. Escenario 6. Los productores cambian al nuevo l\u00edder<\/i><\/p>\n<p>Se perder\u00e1n todos los registros confirmados realizados por el l\u00edder original desde el momento de la p\u00e9rdida de conectividad. Una vez que la red se restablezca, el l\u00edder original a trav\u00e9s de Zookeeper descubrir\u00e1 que ya no es el l\u00edder. Luego truncar\u00e1 su registro hasta el HW del nuevo l\u00edder en el momento de la elecci\u00f3n y comenzar\u00e1 a enviar solicitudes como seguidor.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ frente a Kafka: tolerancia a fallos y alta disponibilidad\" src=\"\/wp-content\/uploads\/2019\/11\/10f0983a829b03ca9bbc62e12cbf8a5d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 35. Escenario 6. El l\u00edder original se convierte en seguidor tras la restauraci\u00f3n de la conectividad de la red.<\/i><\/p>\n<p>En esta situaci\u00f3n, puede observarse una divisi\u00f3n l\u00f3gica a corto plazo, pero solo si <i>acks=1<\/i> y <i>min.insync.replicas<\/i> tambi\u00e9n 1. La divisi\u00f3n l\u00f3gica se termina autom\u00e1ticamente ya sea despu\u00e9s de restaurar la red, cuando el l\u00edder original se da cuenta de que ya no es l\u00edder, o cuando todos los clientes entienden que el l\u00edder ha cambiado y comienzan a escribir al nuevo l\u00edder, dependiendo de lo que ocurra primero. En cualquier caso, se perder\u00e1n algunos mensajes, pero solo con <i>acks=1<\/i>.<\/p>\n<p>Hay otra variante de este escenario, cuando justo antes de la divisi\u00f3n de la red, los seguidores se retrasan y el l\u00edder contrae el ISR a s\u00ed mismo. Luego se a\u00edsla debido a la p\u00e9rdida de conectividad. Se elige un nuevo l\u00edder, pero el l\u00edder original sigue aceptando registros, incluso <i>acks=all.<\/i>, porque en el ISR no hay nadie m\u00e1s que \u00e9l. Estos registros se perder\u00e1n una vez que se restablezca la red. La \u00fanica forma de evitar este escenario es <i>min.insync.replicas = 2<\/i>.<\/p>\n<h3>Escenario 7. El nodo controlador de Kafka no ve a otro nodo de Kafka.<\/h3>\n<p>\nEn general, tras perder conexi\u00f3n con un nodo de Kafka, el controlador no podr\u00e1 transmitirle ninguna informaci\u00f3n sobre el cambio de l\u00edder. En el peor de los casos, esto conducir\u00e1 a una breve divisi\u00f3n l\u00f3gica, como en el escenario 6. Con mayor frecuencia, el corredor simplemente no ser\u00e1 candidato a liderazgo en caso de que el \u00faltimo falle.<\/p>\n<h3>Escenario 8. El controlador de Kafka no ve a Zookeeper.<\/h3>\n<p>\nEl controlador de Zookeeper ca\u00eddo no recibir\u00e1 un ping y elegir\u00e1 como controlador un nuevo nodo de Kafka. El controlador original puede seguir consider\u00e1ndose como tal, pero no recibe notificaciones de Zookeeper, por lo que no tendr\u00e1 tareas que realizar. Una vez que la red se restablezca, se dar\u00e1 cuenta de que ya no es un controlador, sino un nodo normal de Kafka.<\/p>\n<h3>Conclusiones de los escenarios<\/h3>\n<p>\nObservamos que la p\u00e9rdida de conectividad de los seguidores no conduce a la p\u00e9rdida de mensajes, sino que simplemente reduce temporalmente la redundancia hasta que la red se restablezca. Esto, por supuesto, puede resultar en la p\u00e9rdida de datos si uno o m\u00e1s nodos se pierden.<\/p>\n<p>Si debido a la p\u00e9rdida de conectividad el l\u00edder se separa de Zookeeper, esto puede conducir a la p\u00e9rdida de mensajes con <i>acks=1<\/i>. La falta de conexi\u00f3n con Zookeeper provoca una breve separaci\u00f3n l\u00f3gica con dos l\u00edderes. Este problema se resuelve con el par\u00e1metro <i>acks=all.<\/i>.<\/p>\n<p>Par\u00e1metro <i>min.insync.replicas<\/i> de dos o m\u00e1s r\u00e9plicas que proporcionan garant\u00edas adicionales de que tales escenarios a corto plazo no provocar\u00e0n la p\u00e9rdida de mensajes, como en el escenario 6.<\/p>\n<h1>Resumen sobre la p\u00e9rdida de mensajes<\/h1>\n<p>\nEnumeremos todas las formas en que se pueden perder datos en Kafka:<\/p>\n<ul>\n<li>Cualquier fallo del l\u00edder, si los mensajes fueron confirmados mediante <i>acks=1<\/i>\n<\/li>\n<li>Cualquier transici\u00f3n de liderazgo sucia (unclean), es decir, hacia un seguidor fuera de ISR, incluso con <i>acks=all.<\/i>\n<\/li>\n<li>Aislamiento del l\u00edder de Zookeeper, si los mensajes fueron confirmados mediante <i>acks=1<\/i>\n<\/li>\n<li>Aislamiento total del l\u00edder que ya ha comprimido el grupo ISR a s\u00ed mismo. Se perder\u00e1n todos los mensajes, incluso <i>acks=all.<\/i>. Esto es cierto solo si <i>min.insync.replicas=1<\/i>.\n<\/li>\n<li>Fallos simult\u00e1neos de todos los nodos de la partici\u00f3n. Dado que los mensajes se confirman desde la memoria, algunos pueden no haberse escrito a\u00fan en el disco. Despu\u00e9s de reiniciar los servidores, pueden faltar algunos mensajes.<\/li>\n<\/ul>\n<p>\nSe pueden evitar las transiciones de liderazgo sucias, ya sea prohibi\u00e9ndolas o asegurando una redundancia de al menos dos. La configuraci\u00f3n m\u00e1s robusta es una combinaci\u00f3n de <i>acks=all.<\/i> y <i>min.insync.replicas<\/i> m\u00e1s de 1.<\/p>\n<h1>Comparaci\u00f3n directa de la fiabilidad de RabbitMQ y Kafka<\/h1>\n<p>\nPara garantizar la fiabilidad y alta disponibilidad, ambas plataformas implementan un sistema de replicaci\u00f3n primaria y secundaria. Sin embargo, RabbitMQ tiene un tal\u00f3n de Aquiles. Al reconectarse despu\u00e9s de una falla, los nodos descartan sus datos y la sincronizaci\u00f3n se bloquea. Este doble golpe pone en duda la durabilidad de las grandes colas en RabbitMQ. Tendr\u00e1 que lidiar con una menor redundancia o con prolongados bloqueos. La reducci\u00f3n de la redundancia aumenta el riesgo de p\u00e9rdida masiva de datos. Pero si las colas son peque\u00f1as, se puede manejar la garant\u00eda de redundancia con cortos per\u00edodos de inactividad (unos segundos) mediante reintentos de conexi\u00f3n.<\/p>\n<p>En Kafka no existe tal problema. Descarta datos solo desde el punto de discrepancia entre el l\u00edder y el seguidor. Todos los datos comunes se mantienen. Adem\u00e1s, la replicaci\u00f3n no bloquea el sistema. El l\u00edder sigue aceptando registros mientras un nuevo seguidor lo alcanza, por lo que para los DevOps unirse o reunirse al cl\u00faster se convierte en una tarea trivial. Por supuesto, todav\u00eda existen problemas, como el ancho de banda de la red durante la replicaci\u00f3n. Si se a\u00f1aden varios seguidores al mismo tiempo, se puede enfrentar a un l\u00edmite de ancho de banda.<\/p>\n<p>RabbitMQ supera a Kafka en confiabilidad cuando varios servidores fallan simult\u00e1neamente en el cl\u00faster. Como ya hemos mencionado, RabbitMQ enviar\u00e1 una confirmaci\u00f3n al publicador solo despu\u00e9s de que el mensaje haya sido escrito en disco en el maestro y en todos los espejos. Pero esto a\u00f1ade una latencia adicional por dos razones:<\/p>\n<ul>\n<li>fsync cada pocos cientos de milisegundos\n<\/li>\n<li>Las fallas en los espejos solo se pueden detectar despu\u00e9s de que expira el tiempo de vida de los paquetes que verifican la disponibilidad de cada nodo (tick de red). Si un espejo se ralentiza o cae, esto a\u00f1ade latencia.<\/li>\n<\/ul>\n<p>\nKafka apuesta a que si un mensaje se almacena en varios nodos, se pueden confirmar los mensajes tan pronto como lleguen a la memoria. Esto conlleva el riesgo de p\u00e9rdida de mensajes de cualquier tipo (incluso <i>acks=all.<\/i>, <i>min.insync.replicas=2<\/i>) en caso de fallos simult\u00e1neos.<\/p>\n<p>En general, Kafka muestra un rendimiento m\u00e1s alto y est\u00e1 dise\u00f1ado originalmente para cl\u00fasteres. El n\u00famero de seguidores se puede aumentar a 11 si se necesita para la confiabilidad. Un factor de replicaci\u00f3n de 5 y un n\u00famero m\u00ednimo de r\u00e9plicas en estado sincronizado <i>min.insync.replicas=3<\/i> har\u00e1n que la p\u00e9rdida de mensajes sea un evento muy raro. Si su infraestructura puede garantizar tal factor de replicaci\u00f3n y nivel de redundancia, puede optar por esta opci\u00f3n.<\/p>\n<p>La agrupaci\u00f3n de RabbitMQ es buena para colas peque\u00f1as. Pero incluso las colas peque\u00f1as pueden crecer r\u00e1pidamente bajo un gran tr\u00e1fico. Una vez que las colas se vuelven grandes, tendr\u00e1 que hacer una dura elecci\u00f3n entre disponibilidad y confiabilidad. La agrupaci\u00f3n de RabbitMQ es m\u00e1s adecuada para situaciones poco comunes, donde las ventajas de flexibilidad de RabbitMQ superan cualquier inconveniente de su agrupaci\u00f3n.<\/p>\n<p>Una de las contramedidas a la vulnerabilidad de RabbitMQ en relaci\u00f3n con las colas grandes es dividirlas en muchas m\u00e1s peque\u00f1as. Si no se requiere un orden completo de toda la cola, sino solo de los mensajes pertinentes (por ejemplo, los mensajes de un cliente espec\u00edfico), o incluso si no se ordena nada, esta opci\u00f3n es aceptable: mira mi proyecto <noindex><a rel=\"nofollow\" href=\"https:\/\/jack-vanlightly.com\/blog\/2018\/7\/22\/creating-consumer-groups-in-rabbitmq-with-rebalanser-part-1\">Rebalanceador<\/a><\/noindex> para dividir la cola (el proyecto est\u00e1 a\u00fan en una etapa temprana). <\/p>\n<p>Finalmente, no olvides una serie de errores en los mecanismos de clustering y replicaci\u00f3n tanto de RabbitMQ como de Kafka. Con el tiempo, los sistemas se han vuelto m\u00e1s maduros y estables, pero ning\u00fan mensaje estar\u00e1 100% protegido contra la p\u00e9rdida. Adem\u00e1s, ocurren grandes desastres en los centros de datos.<\/p>\n<p>Si he pasado algo por alto, he cometido un error o no est\u00e1s de acuerdo con alguno de los puntos, no dudes en dejar un comentario o contactarme.<\/p>\n<p>A menudo me preguntan: '\u00bfQu\u00e9 elegir, Kafka o RabbitMQ?', '\u00bfCu\u00e1l plataforma es mejor?'. La verdad es que realmente depende de tu situaci\u00f3n, experiencia actual, etc. No me atrevo a expresar mi opini\u00f3n, ya que ser\u00eda una simplificaci\u00f3n excesiva recomendar una \u00fanica plataforma para todos los casos de uso y posibles limitaciones. He escrito esta serie de art\u00edculos para que puedas formar tu propia opini\u00f3n.<\/p>\n<p>Quiero decir que ambos sistemas son l\u00edderes en este campo. Puede que est\u00e9 un poco sesgado, ya que por la experiencia de mis proyectos tiendo a valorar cosas como la garant\u00eda de orden de mensajes y la fiabilidad. <\/p>\n<p>Veo otras tecnolog\u00edas que carecen de esta fiabilidad y de un orden garantizado, luego miro a RabbitMQ y Kafka, y comprendo el incre\u00edble valor de ambos sistemas.<br \/>\n<br \/>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/474984\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044e RabbitMQ \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 \u0438 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u043f\u043e\u043a\u043e\u043f\u0430\u0435\u043c\u0441\u044f \u0432 Apache Kafka. \u0417\u0434\u0435\u0441\u044c \u0435\u0434\u0438\u043d\u0438\u0446\u0435\u0439 \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0434\u0435\u043b (partition). \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430 \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432. \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u0435\u0441\u0442\u044c \u043b\u0438\u0434\u0435\u0440 \u0441 \u0444\u043e\u043b\u043b\u043e\u0432\u0435\u0440\u0430\u043c\u0438 \u0438\u043b\u0438 \u0431\u0435\u0437 \u043d\u0438\u0445. \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u043f\u0438\u043a\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432 \u0438 \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0438. \u041e\u0431\u044b\u0447\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 3, \u044d\u0442\u043e [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52541","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47RabbitMQ \u043f\u0440\u043e\u0442\u0438\u0432 Kafka: \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-11-10T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:17+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47RabbitMQ vs Kafka: alta disponibilidad y tolerancia a fallos | ProHoster","description":"En","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47RabbitMQ \u043f\u0440\u043e\u0442\u0438\u0432 Kafka: \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c | ProHoster","og:description":"\u0412","og:url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-11-10T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:17+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52541","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 03:57:21","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:41:24","updated":"2026-01-24 03:57:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/52541","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=52541"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/52541\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=52541"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=52541"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=52541"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}