{"id":14870,"date":"2025-06-18T08:26:11","date_gmt":"2025-06-18T06:26:11","guid":{"rendered":"https:\/\/www.palentino.es\/blog\/?p=14870"},"modified":"2025-06-18T08:32:11","modified_gmt":"2025-06-18T06:32:11","slug":"esquema-de-uso-de-un-balanceador-de-carga-mysql-con-haproxy","status":"publish","type":"post","link":"https:\/\/www.palentino.es\/blog\/esquema-de-uso-de-un-balanceador-de-carga-mysql-con-haproxy\/","title":{"rendered":"Esquema de uso de un balanceador de Carga MySQL con HAProxy"},"content":{"rendered":"<p>En la era de las aplicaciones conectadas 24\/7, el rendimiento y la disponibilidad de las bases de datos son aspectos <strong>cruciales<\/strong>. Cuando una \u00fanica instancia MySQL empieza a recibir cientos o miles de conexiones simult\u00e1neas, se convierte en un cuello de botella que puede poner en riesgo la experiencia de los usuarios o incluso provocar ca\u00eddas del sistema.<\/p>\n<p>Para solucionar esto, una estrategia com\u00fan y eficiente es implementar un <strong>balanceador de carga<\/strong> que distribuya las conexiones entre varios servidores de bases de datos. Esta arquitectura mejora el rendimiento general, permite escalar horizontalmente y aporta alta disponibilidad.<\/p>\n<p>Entre las herramientas m\u00e1s utilizadas para este prop\u00f3sito destaca <strong>HAProxy (High Availability Proxy)<\/strong>, un proxy TCP\/HTTP de alto rendimiento y muy liviano, que permite distribuir de forma inteligente las conexiones entrantes hacia diferentes nodos MySQL, ya sea en configuraci\u00f3n maestro-esclavo o multi-master.<\/p>\n<p>En esta entrada aprender\u00e1s c\u00f3mo se estructura un entorno con HAProxy como punto central de entrada para una arquitectura MySQL distribuida. No nos enfocaremos en comandos ni instalaci\u00f3n paso a paso, sino en <strong>entender el flujo, los componentes y las ventajas pr\u00e1cticas<\/strong> de este enfoque.<\/p>\n<p><!--more--><\/p>\n<hr \/>\n<h2>&#x1f9f1; Arquitectura del sistema<\/h2>\n<p>Supongamos que tenemos el siguiente entorno:<\/p>\n<table style=\"height: 154px;\" width=\"606\">\n<thead>\n<tr>\n<th>Componente<\/th>\n<th>IP<\/th>\n<th>Puerto<\/th>\n<th>Rol<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Aplicaci\u00f3n web<\/td>\n<td>\u2014<\/td>\n<td>\u2014<\/td>\n<td>Cliente<\/td>\n<\/tr>\n<tr>\n<td>HAProxy<\/td>\n<td>192.168.1.100<\/td>\n<td>3307<\/td>\n<td>Balanceador<\/td>\n<\/tr>\n<tr>\n<td>MySQL Master<\/td>\n<td>192.168.1.10<\/td>\n<td>3306<\/td>\n<td>Escritura<\/td>\n<\/tr>\n<tr>\n<td>MySQL Slave<\/td>\n<td>192.168.1.11<\/td>\n<td>3306<\/td>\n<td>Lectura<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h2>&#x1f4d0; Esquema Visual del Flujo<\/h2>\n<p><a href=\"https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2025\/06\/Balanceador-carga.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-14875\" src=\"https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2025\/06\/Balanceador-carga.png\" alt=\"\" width=\"562\" height=\"724\" srcset=\"https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2025\/06\/Balanceador-carga.png 562w, https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2025\/06\/Balanceador-carga-233x300.png 233w\" sizes=\"auto, (max-width: 562px) 100vw, 562px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2>&#x1f504; Flujo de funcionamiento<\/h2>\n<ol>\n<li>La <strong>aplicaci\u00f3n<\/strong> se conecta \u00fanicamente a <strong>HAProxy<\/strong> (IP 192.168.1.100, puerto 3307).<\/li>\n<li>HAProxy recibe cada conexi\u00f3n y la redirige a uno de los servidores MySQL seg\u00fan su configuraci\u00f3n.\n<ul>\n<li>En modo simple: balanceo <strong>round-robin<\/strong> entre todos los nodos disponibles.<\/li>\n<li>En modo avanzado: se pueden usar puertos o usuarios distintos para separar lecturas y escrituras.<\/li>\n<\/ul>\n<\/li>\n<li>El servidor <strong>MySQL Master<\/strong> ejecuta operaciones de <strong>escritura<\/strong> (INSERT, UPDATE, DELETE).<\/li>\n<li>El servidor <strong>MySQL Slave<\/strong> responde a consultas de <strong>lectura<\/strong> (SELECT), evitando cargar al maestro.<\/li>\n<li>El balanceo es <strong>totalmente transparente<\/strong> para la aplicaci\u00f3n: no necesita conocer cu\u00e1ntos servidores hay detr\u00e1s ni su rol.<\/li>\n<\/ol>\n<hr \/>\n<h2>&#x1f9e0; Mejora recomendada: separaci\u00f3n por puertos<\/h2>\n<p>Una pr\u00e1ctica com\u00fan en entornos productivos es crear <strong>dos frontends<\/strong> en HAProxy:<\/p>\n<ul>\n<li>&#x1f535; <strong>Puerto 3308<\/strong> \u2192 Solo para lecturas (dirigido a los slaves)<\/li>\n<li>&#x1f534; <strong>Puerto 3309<\/strong> \u2192 Solo para escrituras (dirigido al master)<\/li>\n<\/ul>\n<p>As\u00ed, la aplicaci\u00f3n puede conectarse a un puerto u otro dependiendo del tipo de operaci\u00f3n, permitiendo un control total desde la capa l\u00f3gica del sistema.<\/p>\n<hr \/>\n<h2>&#x2705; Ventajas de usar HAProxy para MySQL<\/h2>\n<ul>\n<li><strong>Alta disponibilidad<\/strong>: si un nodo falla, las conexiones se redirigen autom\u00e1ticamente a otros disponibles.<\/li>\n<li><strong>Escalabilidad horizontal<\/strong>: se pueden agregar m\u00e1s r\u00e9plicas de lectura sin reconfigurar la aplicaci\u00f3n.<\/li>\n<li><strong>Transparencia<\/strong>: la aplicaci\u00f3n sigue conect\u00e1ndose a un \u00fanico punto.<\/li>\n<li><strong>Flexibilidad<\/strong>: puedes configurar reglas, pesos, salud de nodos, failover autom\u00e1tico y m\u00e1s.<\/li>\n<li><strong>Ligereza y velocidad<\/strong>: HAProxy maneja miles de conexiones con consumo m\u00ednimo de recursos.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>\u00a1Perfecto! Aqu\u00ed tienes la <strong>parte que faltaba: c\u00f3mo implementar paso a paso<\/strong> el esquema de balanceo de carga MySQL con HAProxy. Este bloque completa la entrada anterior y est\u00e1 pensado para ser claro, funcional y apto para entornos reales.<\/p>\n<hr \/>\n<h2>&#x1f6e0;&#xfe0f; C\u00f3mo implementar un balanceador de carga MySQL con HAProxy<\/h2>\n<p>Aqu\u00ed te explico <strong>c\u00f3mo montar el entorno completo paso a paso<\/strong>, desde la instalaci\u00f3n de HAProxy hasta la conexi\u00f3n desde la aplicaci\u00f3n.<\/p>\n<hr \/>\n<h3>&#x2705; Requisitos previos<\/h3>\n<ul>\n<li>Un servidor <strong>MySQL Master<\/strong> (IP: 192.168.1.10)<\/li>\n<li>Un servidor <strong>MySQL Slave<\/strong> con replicaci\u00f3n configurada (IP: 192.168.1.11)<\/li>\n<li>Un servidor para <strong>HAProxy<\/strong> (IP: 192.168.1.100)<\/li>\n<li>Un usuario MySQL com\u00fan en ambos nodos (root, por ejemplo)<\/li>\n<li>Sistema operativo Ubuntu\/Debian en el balanceador<\/li>\n<\/ul>\n<hr \/>\n<h3>&#x1f4e6; Paso 1: Instalar HAProxy<\/h3>\n<p>En el servidor que actuar\u00e1 como balanceador:<\/p>\n<pre>\n\n<div class=\"codecolorer-container text mac-classic language-bash\" style=\"overflow:auto;white-space:nowrap;width:635px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/><\/div><\/td><td><div class=\"text codecolorer\">sudo apt update<br \/>\nsudo apt install haproxy -y<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n<\/pre>\n<hr \/>\n<h3>&#x1f510; Paso 2: Crear usuario de salud para HAProxy en MySQL<\/h3>\n<p>En <strong>master<\/strong> y <strong>slave<\/strong>, ejecuta:<\/p>\n<pre>\n\n<div class=\"codecolorer-container text mac-classic language-sql\" style=\"overflow:auto;white-space:nowrap;width:635px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/><\/div><\/td><td><div class=\"text codecolorer\">CREATE USER 'haproxy_check'@'%' IDENTIFIED BY 'check';<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n<\/pre>\n<p>Este usuario se usa para verificar si el nodo est\u00e1 disponible.<\/p>\n<hr \/>\n<h3>&#x1f9e9; Paso 3: Configurar HAProxy<\/h3>\n<p>Edita el archivo \/etc\/haproxy\/haproxy.cfg y reempl\u00e1zalo por esta configuraci\u00f3n b\u00e1sica:<\/p>\n<pre>\n\n<div class=\"codecolorer-container text mac-classic language-ini\" style=\"overflow:auto;white-space:nowrap;width:635px;height:300px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/><\/div><\/td><td><div class=\"text codecolorer\">global<br \/>\n&nbsp; &nbsp; log \/dev\/log local0<br \/>\n&nbsp; &nbsp; maxconn 2000<br \/>\n&nbsp; &nbsp; daemon<br \/>\n<br \/>\ndefaults<br \/>\n&nbsp; &nbsp; mode tcp<br \/>\n&nbsp; &nbsp; log global<br \/>\n&nbsp; &nbsp; option tcplog<br \/>\n&nbsp; &nbsp; timeout connect 5s<br \/>\n&nbsp; &nbsp; timeout client &nbsp;1m<br \/>\n&nbsp; &nbsp; timeout server &nbsp;1m<br \/>\n<br \/>\nfrontend mysql_front<br \/>\n&nbsp; &nbsp; bind *:3307<br \/>\n&nbsp; &nbsp; default_backend mysql_back<br \/>\n<br \/>\nbackend mysql_back<br \/>\n&nbsp; &nbsp; mode tcp<br \/>\n&nbsp; &nbsp; balance roundrobin<br \/>\n&nbsp; &nbsp; option mysql-check user haproxy_check<br \/>\n&nbsp; &nbsp; server mysql-master 192.168.1.10:3306 check<br \/>\n&nbsp; &nbsp; server mysql-slave &nbsp;192.168.1.11:3306 check<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n<\/pre>\n<hr \/>\n<h3>&#x1f504; Paso 4: Reiniciar y habilitar HAProxy<\/h3>\n<pre>\n\n<div class=\"codecolorer-container text mac-classic language-bash\" style=\"overflow:auto;white-space:nowrap;width:635px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/><\/div><\/td><td><div class=\"text codecolorer\">sudo systemctl restart haproxy<br \/>\nsudo systemctl enable haproxy<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n<\/pre>\n<hr \/>\n<h3>&#x1f50e; Paso 5: Probar la conexi\u00f3n<\/h3>\n<p>Desde cualquier cliente MySQL o desde la app:<\/p>\n<pre>\n\n<div class=\"codecolorer-container text mac-classic language-bash\" style=\"overflow:auto;white-space:nowrap;width:635px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/><\/div><\/td><td><div class=\"text codecolorer\">mysql -u root -p -h 192.168.1.100 -P3307<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n<\/pre>\n<p>Prueba varias veces, ejecuta SELECT o SHOW PROCESSLIST, y ver\u00e1s c\u00f3mo las conexiones van rotando entre los nodos disponibles.<\/p>\n<hr \/>\n<h3>&#x1f9e0; Mejora opcional: puertos separados para lectura y escritura<\/h3>\n<p>Si quieres separar expl\u00edcitamente:<\/p>\n<pre>\n\n<div class=\"codecolorer-container text mac-classic language-ini\" style=\"overflow:auto;white-space:nowrap;width:635px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/><\/div><\/td><td><div class=\"text codecolorer\">frontend mysql_read<br \/>\n&nbsp; &nbsp; bind *:3308<br \/>\n&nbsp; &nbsp; default_backend mysql_reads<br \/>\n<br \/>\nfrontend mysql_write<br \/>\n&nbsp; &nbsp; bind *:3309<br \/>\n&nbsp; &nbsp; default_backend mysql_writes<br \/>\n<br \/>\nbackend mysql_reads<br \/>\n&nbsp; &nbsp; balance roundrobin<br \/>\n&nbsp; &nbsp; option mysql-check user haproxy_check<br \/>\n&nbsp; &nbsp; server slave1 192.168.1.11:3306 check<br \/>\n<br \/>\nbackend mysql_writes<br \/>\n&nbsp; &nbsp; balance roundrobin<br \/>\n&nbsp; &nbsp; option mysql-check user haproxy_check<br \/>\n&nbsp; &nbsp; server master 192.168.1.10:3306 check<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n<\/pre>\n<p>Luego:<\/p>\n<ul>\n<li>App de lectura \u2192 192.168.1.100:3308<\/li>\n<li>App de escritura \u2192 192.168.1.100:3309<\/li>\n<\/ul>\n<hr \/>\n<h2>&#x1f4cc; Resultado final<\/h2>\n<p>Tu aplicaci\u00f3n ya se puede conectar a un solo punto (192.168.1.100:3307) y HAProxy gestionar\u00e1 el resto:<\/p>\n<ul>\n<li>Repartiendo carga<\/li>\n<li>Verificando salud de los nodos<\/li>\n<li>Aislando nodos ca\u00eddos<\/li>\n<li>Escalando sin tocar la app<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<hr \/>\n<h2>&#x1f4dd; Conclusi\u00f3n<\/h2>\n<p>Entender el esquema de uso de HAProxy en entornos MySQL es clave para cualquier arquitecto o administrador de sistemas que busque fiabilidad, rendimiento y flexibilidad en su infraestructura. Esta soluci\u00f3n se adapta tanto a proyectos peque\u00f1os como a grandes plataformas en producci\u00f3n.<\/p>\n<p>Ya sea que est\u00e9s implementando alta disponibilidad, escalabilidad horizontal o simplemente buscando distribuir carga de lectura, HAProxy es una herramienta robusta y bien documentada para acompa\u00f1arte en ese camino.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>En la era de las aplicaciones conectadas 24\/7, el rendimiento y la disponibilidad de las bases de datos son aspectos cruciales. Cuando una \u00fanica instancia MySQL empieza a recibir cientos o miles de conexiones simult\u00e1neas, se convierte en un cuello de botella que puede poner en riesgo la experiencia de los usuarios o incluso provocar ca\u00eddas del sistema. Para solucionar esto, una estrategia com\u00fan y eficiente es implementar un balanceador de carga que distribuya las conexiones entre varios servidores de bases de datos. Esta arquitectura mejora el rendimiento general, permite escalar horizontalmente y aporta alta disponibilidad. Entre las herramientas m\u00e1s utilizadas para este prop\u00f3sito destaca HAProxy (High Availability Proxy), un proxy TCP\/HTTP de alto rendimiento y muy liviano, que permite distribuir de forma inteligente las conexiones entrantes hacia diferentes nodos MySQL, ya sea en configuraci\u00f3n maestro-esclavo o multi-master. En esta entrada aprender\u00e1s c\u00f3mo se estructura un entorno con HAProxy como punto central de entrada para una arquitectura MySQL distribuida. No nos enfocaremos en comandos ni instalaci\u00f3n paso a paso, sino en entender el flujo, los componentes y las ventajas pr\u00e1cticas de este enfoque.<\/p>\n","protected":false},"author":1,"featured_media":4871,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[620],"tags":[],"class_list":["post-14870","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-mysql"],"_links":{"self":[{"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/posts\/14870","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/comments?post=14870"}],"version-history":[{"count":6,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/posts\/14870\/revisions"}],"predecessor-version":[{"id":14877,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/posts\/14870\/revisions\/14877"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/media\/4871"}],"wp:attachment":[{"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/media?parent=14870"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/categories?post=14870"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/tags?post=14870"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}