Cómo iniciar una replicación Maestro - Esclavo en MySQL >5.0

Lun 3, Diciembre 2007

La replicación en MySQL funciona de una manera muy sencilla. Existe un maestro, que es el encargado de propagar los cambios y los esclavos, que son los que reciben estos cambios a fin de tener una copia exacta de lo que tiene el maestro.

Para que esto suceda, los esclavos tienen una conexión abierta contínua con el maestro para recibir estos cambios. Con esta conexión se comprueba desde el esclavo la última posición escrita en el log binario del maestro -eso es, se replican por medio del log binario. Cuando sucede algún cambio en el log binario del maestro, se remiten estos cambios a los esclavos, que posteriormente ejecutan estos cambios en sus tabla.s

Para empezar una replicación maestro esclavo sencilla hay que tener como mínimo dos instancias del servidor MySQL, una que haga de maestro y otra que haga de esclavo.

En el maestro tienen que estar las siguientes líneas en el fichero de configuración [my.cnf]:

log-bin=mysql-bin
server-id = 1

Por otro lado, en el esclavo tendremos que tener las siguientes lineas:

server-id = 2

Una vez configurados los servidores, podemos arrancarlos -obviamente aún no van a replicar porque no les hemos indicado que empiecen a replicar.

Cuando estén arrancados, en el maestro creamos o instalamos las tablas y la base de datos que queremos replicar. Cuando estén creadas y hayamos insertado los datos necesarios dentro de las tablas entonces tendremos que hacer un volcado de la base de datos a un archivo de texto. La razón de esto es que vamos a instalar esta misma base de datos en el esclavo. Para ello lo podremos hacer así:

mysql> GRANT REPLICATION PRIVILEGES ON *.bbdd TO ‘usuario_replicacion’@'192.168.0.3′ IDENTIFIED BY ‘pass_replicacion’;
mysql> flush privileges;
mysql> LOCK ALL TABLES READ ONLY
mysql> exit

Ahora desde la línea de comandos sacamos un DUMP del maestro:

joax@maestro> mysqldump bbdd > bbdd_dump_20071202.sql

Una vez terminado el proceso, tenemos que recordar la situación del log binario en el master:

mysql> SHOW MASTER STATUS;
+——————+———-+————–+——————+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+——————+———-+————–+——————+
| mysql-bin.000005 | 98 | | |
+——————+———-+————–+——————+
1 row in set (0.00 sec)

Con esto ya podemos desbloquear las tablas en el maestro:

mysql> UNLOCK ALL TABLES;

Y con ello, en el esclavo ahora ejecutamos lo siguiente:

joax@esclavo> mysql bbdd < bbdd_dump_20071202.sql

Y una vez que el esclavo tenga generada la base de datos, lo configuramos para que esté posicionado con respecto al maestro:

mysql> CHANGE MASTER TO MASTER_HOST = ‘192.168.0.2′;
mysql> CHANGE MASTER TO MASTER_USER = ‘usuario_replicacion’;
mysql> CHANGE MASTER TO MASTER_PASSWORD = ‘pass_replicacion’;
mysql> CHANGE MASTER TO MASTER_LOG_FILE = ‘mysql-bin.000005′;
mysql> CHANGE MASTER TO MASTER_LOG_POS = 98;
mysql> start slave;

Ahora el esclavo comenzará la replicación con el maestro. Quedándose a 0 segundos de él una vez copiado todo el log binario que le resta de lo sucedido hasta la fecha. Para comprobar que realmente está replicando, tendremos que ejecutar el siguiente comando en la consola de MySQL:

mysql> show slave status \G

Eso muestra:

*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.0.2
Master_User: usuario_replicacion
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 98
Relay_Log_File: esclavo-relay-bin.000001
Relay_Log_Pos: 98
Relay_Master_Log_File: mysql-bin.000005
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: bbdd
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 98
Relay_Log_Space: 98
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)

Lo importante es lo que sigue a Seconds_Behind_Master: porque es el valor que indica el retraso de este esclavo con respecto al maestro.

En definitiva y a modo de resumen:

1. Cambiar la configuración del maestro con las líneas:

server-id=1
log-bin=mysql-bin

2. Cambiar la configuración del esclavo:

server-id=2

3. Bloquear las tablas del maestro y hacer un dump:

mysql> LOCK ALL TABLES READ ONLY
mysql> SHOW MASTER STATUS
mysql> exit
joax@maestro> mysqldump bbdd > bbdd_dump_20071202.sql

4. Instalar la base de datos en el esclavo:

joax@esclavo> mysql bbdd < bbdd_dump_20071202.sql
mysql> CHANGE MASTER TO MASTER_HOST = ‘192.168.0.2′;
mysql> CHANGE MASTER TO MASTER_USER = ‘usuario_replicacion’;
mysql> CHANGE MASTER TO MASTER_PASSWORD = ‘pass_replicacion’;
mysql> CHANGE MASTER TO MASTER_LOG_FILE = ‘mysql-bin.000005′;
mysql> CHANGE MASTER TO MASTER_LOG_POS = 98;
mysql> start slave;

En un cluster podremos incluir tantos esclavos como necesitemos. He llegado a ver clusteres de varias decenas de esclavos sobre el mismo maestro. Pero son puntos donde a lo mejor tienes que tomar una estrategia de particionado de la base de datos. Estrategia que veremos próximamente.


La escalabilidad, una asignatura pendiente

Sab 1, Diciembre 2007

Desde hace varios meses, la escalabilidad está siendo mi única materia de estudio y aplicación. No paro de investigar, hacer y deshacer. Y digo deshacer porque una de las cosas más importantes que he aprendido de esta materia es que no se pueden leer blogs aleatoriamente y hacer lo que dicen.

Una vez estuve leyendo un blog de un americano que aseguraba que haciendo una configuración específica a MySQL se podría aumentar su eficencia en la concurrencia. Como no teníamos otra cosa que hacer, lo probamos. Claro, esto de probar las cosas está bien hasta que te pegas el castañazo. Más bien el trompazo. Porque cuando activamos esta nueva configuración, los esclavos de la base de datos empezaron a caer uno detrás de otro como moscas. Menos mal que sólo cambiamos esta configuración en unos cuantos por lo que el portal no sufrió consecuencias y seguía funcionando.

Pero aprendí desde ese momento que cuando alguien en internet habla de escalabilidad o de posibles ideas para solventar este problema tienes que tener claro o seguro que en realidad ha tenido experiencia en ese campo.

Otra anécdota que puedo contar es que en los inicios de tuenti, estábamos otro compañero y yo por la noche haciendo cambios varios sobre la estructura de datos. Hasta que nos topamos con la duda de si aplicar estos cambios a las tablas en el portal. Leyendo la documentación de MySQL 5.0, aseguraba que en un entorno maestro-esclavo hacer cambios en las tablas con ALTER no debiera afectar en absoluto al rendimiento del sistema puesto que el ALTER se realiza sobre una copia temporal de la tabla, por lo que las lecturas podrían seguir sucediendo en la misma tabla durante la operación. Por lo que tanto Kenny como yo decidimos que podríamos hacerlo sin problemas.

Ya podréis saber el resultado de esta acción por cómo estoy empezando esta frase. Si, casi desastre. El maestro comenzó a retener las escrituras sobre la tabla y de esta manera reteniendo las conexiones desde el PHP. Esto hizo que se sobrepasara el límite de conexiones que el servidor tenía previsto -y eso que lo aumentamos en mucho sabiendo que podría pasar… Esto formó una espiral de acontecimientos que nos obligó a cancelar la operación para que el portal no se cayera.

A lo largo de este tiempo, esta son las cosas que creo claves para tener una buena escalabilidad -que es imposible sin experiencia y conocimiento del sector donde te metes , por supuesto:

  • Las cosas tienen que ser muy simples: todo lo complicado no es escalable, y menos aquellas cosas que precisamente hacemos complicadas para que escalen. Puesto que la complejidad es el peor enemigo de la escalabilidad.
  • Investigación: A la hora de econtrarte con un problema de escalabilidad, probablemente, si no eres uno de los portales más grandes del mundo o con una cierta peculiaridad que no tiene nadie, alguien ha pasado ya por lo mismo que tú. Consulta los blogs, listas de desarrolladores y demás frecuentadas por las personas de otros sitios iguales al tuyo (pero más grandes).
  • Priorización: Es muy importante determinar qué cosas son las más importantes para centrarte en la escalabilidad de ellas. Perder demasiado el tiempo en algo que no es importante en tu portal podría mermar otra prioridad que sin embargo necesita ese tiempo.
  • Iteración constante en los cuellos de botella: Esta tiene su base en la Administración de Sistemas. Pero en realidad se puede aplicar a todo tipo de disciplina que necesita una escalabilidad. En producto nos econtramos contínuamente con cuellos de botella en el código que no pueden ser resueltos con más servidores…
  • Éxito como equipo: Tener en cuenta tus responsabilidades, asumirlas y ejecutarlas es vital para que otros miembros de tu equipo puedan hacer las suyas confiando que tu parte estará hecha. Esto hace que el equipo pueda afrontar los problemas de manera más efectiva.
  • Conocer tu plataforma: Tener una buena plataforma y conocerla son claves para poder escalarla. Si estás usando un framework que no conoces por dentro (ruby on rails) puedes encontrarte en una situación donde las propias librerías pueden no ser escalables.

Algunos de estos puntos vienen de leer este comentario en los blogs relacionados con Youtube.


Tuenti tiene eventos!

Jue 22, Noviembre 2007

Hemos lanzado por fin los eventos en tuenti. Ahora se puede crear un evento e invitar a tus amigos para que asistan. De esa manera podrás quedar con ellos sin tener que estar llamándoles, mandándoles mensajes de teléfono…

Además, puedes añadir descripción, página web, teléfono e incluso comentarios al respecto. Hay tres listas diferentes de personas en un evento:

  • Personas que confirman asistencia
  • Personas que a lo mejor van
  • Personas que aún no han contestado

Gracias a este modelo de eventos, podremos estar al día todos de las reuniones con nuestros amigos, quedadas, partidos, fiestas, etc…

Por  si fuera poco, además hemos añadido la posibilidad de que aquellos que no conseguís invitación para entrar podáis dejarnos vuestro correo para que podamos enviarte cuando podamos una invitación.

Espero que os gusten todas estas cosas, el equipo está muy contento por estas cosas.


Cómo usar Memcached en nuestro código PHP

Dom 18, Noviembre 2007

Memcached es un sistema que se ejecuta en modo servicio que almacena en memoria RAM cualquier dato que se le pida. Las llamadas se hacen por medio de sus librerías en los diferentes lenguajes de programación que soporta y el almacenamiento lo realiza por medio de asociaciones de series de cadenas hash. De esta manera, si yo tengo en mi código por ejemplo un listado completo de provincias que voy a mostrar a los usuarios en una página, en vez de estar todas las veces sacándolas de la Base de Datos, las saco una sola vez -la primera vez que se pidan- y las guardo posteriormente en Memcache. La siguiente vez que me las pidan, miro primero si las tengo en Memcached y las muestro directamente desde él.Para poder usarlo, suponemos que tenemos ya un servicio memcached instalado y que queremos asociar nuestro código a él. Esto lo realizamos cargando primero las librerías memcached dentro de nuestro PHP:

$ pecl install memcache

En nuestro fichero de php.ini insertamos la línea -si no lo ha hecho ya pecl:

extension=memcache.so

Una vez instaladas las librerías, podemos llamar a la clase Memcache desde dentro del código. Lo primero que tenemos que hacer es declarar la clase:


$memcache = new Memcache();
$memcache->pconect(’localhost’,11211);

Aqui supongo que el servicio Memcache está situado en el mismo servidor. Según la documentación de Memcache, el puerto por defecto es el 11211, por lo que usaremos el mismo.

Ahora que estamos conectados, sólo queda usarlo. Por ejemplo, aquí tengo una función que me devuelve las provincias de España:


function get_provincias($pais) {
$prov = $memcache->get(”PROV_”.$pais);
if ( $prov === false) {
// No está en memcache, así que las traigo de la BBDD y las meto en
// memcache para la siguiente vez…
$prov = coge_de_base_datos_provincias($pais);
$memcache->set(”PROV_”.$pais,$prov,0,0);
}
return $prov;
}

Todos los hilos de PHP que corran podrán acceder a la información que otros hilos han dejado dentro del servicio. Por lo que hay que tener cuidado con los accesos y la información que se pueda introducir.

Como podéis observar, es cuestión de mantener una lógica lo sufientemente sencilla como para no confundirse a la hora de manejar los datos. Otro detalle que habréis notado es que he usado dos métodos de la clase Memcache. En realidad los que suelo usar son estos dos nada más. Existen otros muy útiles también como set(), replace(), invalidate().

Este último existe porque tú también puedes definir a Memcache el tiempo máximo que quieres que esa entrada se encuentre en la memoria. Así se pueden mantener datos temporales en memcache como información de la sesión de un usuario. Este valor está definido en segundos por el cuarto parámetro de la función set(). Pero os remito a la documentación que hay aquí para profundizar más en este aspecto.

Memcached es una herramienta muy útil que hará que nuestras aplicaciones web no tengan que esperar esos 10ms a la base de datos ya que este servicio tiene tiempos de respuesta por debajo del milisegundo en muchas ocasiones.


PHP programado en Objetos o sin Objetos

Sab 17, Noviembre 2007

Hoy mismo hemos levantado el nuevo código a producción. Este nuevo código trae novedades que los usuarios no ven, pero que harán que sus páginas vayan más rápido y que dejen de haber errores extraños por la página -alguno quedará seguro, pero al menos la gran mayoría ya no!.

Este nuevo código está en gran parte ya orientado a objetos. Cosas como el tratamiento de las imágenes y las etiquetas están en objetos, así como los usuarios. Esto hace que la lógica en el código sea más rubusta y que por ello hayan menos errores. Así mismo deja la puerta abierta a los programadores del front-end para que les sea más sencillo programar y no tengan que vérselas con las odiosas SQLs y menos con lógicas del PHP profundo que no deberían tocar.

¡Pero no todo son maravillas en el paraíso de la orientación a objetos! Al subir el código y reabrir el portal nos hemos dado cuenta de que nuestros frontales, de estar completamente ociosos (de media un 5% de uso de CPU en dias de pico) han empezado a trabajar. Básicamente donde ayer teníamos un uso en los frontales de un 4% hoy lo tenemos de un 20%. Es decir, que ahora esta programación por objetos se nos ha comido ciclos de los procesadores de nuestros frontales.

Cierto es que hemos añadido lógica más tediosa a los objetos en sí, que hacen llamadas a los byte-coded cachés -APC en concreto- y luego al Memcached. Por lo que puede que todo en conjunto sea el aglutinante de este vertiginoso crecimiento. Pero os puedo decir que es impresionante el crecimiento de uso de CPU que se ha experimentado en tan sólo 4 horas!

Definitivamente puedo decir que la programación por Objetos en PHP tiene muchas ventajas de cara a la producción de código, pero tiene muchas desventajas de cara a los servidores que lo tienen que soportar… Estando en un entorno de alto uso -no voy a decir números- puedo hablar con datos y pruebas sobre ello.

Si quieres una programación limpia y un código sostenible, programa bien. Y si además quieres que ese código sea reusable y que tus programadores de front puedan desarrollar más rápido, programa Objetos! Pero eso sí, ten unos cuantos servidores de reserva preparados, porque los vas a necesitar.


Mi primer post

Sab 17, Noviembre 2007

Ya tenía un blog en su día que programé yo mismo sobre ASP que he decidido dejar de lado. En cambio, voy a empezar a escribir aquí.

En primer lugar me voy a presentar.

Me llamo Joaquín. Tengo 26 años y trabajo en el equipo de tuenti.com, un portal de internet que tiene como misión:

“tuenti.com es la herramienta que te ayuda a tener cerca a la gente que conoces”

Espero poder escribir más posts y que os sean interesantes. Los próximos posts que escriba serán sobre -y así adelanto la temática de este blog:

  • Replicación en alta disponibilidad de MySQL
  • Clústeres en alta disponibilidad de servidores web
  • Optimizaciones de PHP sobre MySQL y Memcache -algo también de APC.
  • Anécdotas divertidas dentro de la tecnología de tuenti.com

Algunos de los posts irán en inglés ya que es el idioma oficial que tenemos en el equipo de tuenti al ser mitad españoles y mitad no españoles -tuenti es 100% español, pero para tecnología y otros menesteres hemos tenido que contar con la inestimable ayuda de compañeros extranjeros.