systemadmin.es > Instalaciones > Replicación en memcached

Replicación en memcached

En teoría los datos contenidos en un memcached deberían ser algo que la aplicación no dependa de su existencia: paginas cacheadas (se pueden regenerar) o sesiones de usuario (se deben volver a autenticar) Si la aplicación dependen mucho de ello o se estima muy importante no perder la sesión del usuario podemos usar replicación de memcached mediante el parche de repcached

Primero de todo vamos a necesitar, igual que cualquier memcached, libevent instalado:

cd /usr/local/src
wget http://monkey.org/~provos/libevent-1.4.8-stable.tar.gz
tar xzf libevent-1.4.8-stable.tar.gz
cd libevent-1.4.8-stable
./configure --prefix=/usr/local/ --exec-prefix=/usr/local/
make && make install

A continuación podemos bajar una versión de memcached ja parcheada desde la web de repcached:

cd /usr/local/src
wget http://sourceforge.net/projects/repcached/files/repcached/2.2-1.2.8/memcached-1.2.8-repcached-2.2.tar.gz/download
tar xzf memcached-1.2.8-repcached-2.2.tar.gz 
cd memcached-1.2.8-repcached-2.2
./configure --prefix=/usr/local/ --exec-prefix=/usr/local/ --enable-64bit --enable-replication

La opción enable-threads es incompatible con la enable-replication
enable-threads, por lo que el memcached resultante sera un solo proceso sin threads.

Para saber como funciona en el man no he visto nada, asi que me he ido a la función main del memcached.c, donde encontramos:

#ifdef USE_REPLICATION
        case 'x':
            if (inet_pton(AF_INET, optarg, &addr) <= 0) {
                memset(&master_hint, 0, sizeof(master_hint));
                master_hint.ai_flags    = 0;
                master_hint.ai_socktype = 0;
                master_hint.ai_protocol = 0;
                if(!getaddrinfo(optarg, NULL, &master_hint, &master_addr)){
                    settings.rep_addr = ((struct sockaddr_in *)(master_addr->ai_addr)) -> sin_addr;
                    freeaddrinfo(master_addr);
                }else{
                    fprintf(stderr, "Illegal address: %s\n", optarg);
                    return 1;
                }
            } else {
                settings.rep_addr = addr;
            }
            break;
        case 'X':
            settings.rep_port = atoi(optarg);
            break;
        case 'q':
            settings.rep_qmax = atoi(optarg);
            break;
#endif /* USE_REPLICATION */

Así entiendo que mediante la opción -x indicamos el peer y con el -X el puerto del peer, asi que lo probamos arrancando una instancia:

# /usr/local/bin/memcached -u memcached -p 11211 -m 64 -x 127.0.0.1 -v
replication: connect (peer=127.0.0.1:11212)
replication: marugoto copying
replication: close
replication: listen

Y una segunda para hacer la replicación:

# /usr/local/bin/memcached -u memcached -p 22322 -m 64 -x 127.0.0.1 -v
replication: connect (peer=127.0.0.1:11212)
replication: accept
replication: marugoto copying
replication: start

A continuación podemos ver los puertos que escucha y la conexión entre los dos memcacheds para replicar los datos:

# netstat -tpan | grep memcache
tcp        0      0 0.0.0.0:22322               0.0.0.0:*                   LISTEN      20069/memcached     
tcp        0      0 0.0.0.0:11211               0.0.0.0:*                   LISTEN      20068/memcached     
tcp        0      0 127.0.0.1:11212             127.0.0.1:50480             ESTABLISHED 20068/memcached     
tcp        0      0 127.0.0.1:50480             127.0.0.1:11212             ESTABLISHED 20069/memcached     

Podemos probar haciendo un set en el primer memcached:

# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
set web 0 0 14            
systemadmin.es
STORED
quit
Connection closed by foreign host.

Y a continuación el get en el segundo:

# telnet localhost 22322
Trying ::1...
Connected to localhost.
Escape character is '^]'.
get web
VALUE web 0 14
systemadmin.es
END
quit
Connection closed by foreign host.

Y el caso inverso, el set en el segundo:

# telnet localhost 22322
Trying ::1...
Connected to localhost.
Escape character is '^]'.
set ejemplo 0 0 14
systemadmin.es
STORED
quit
Connection closed by foreign host.

Y el get en el primero:

# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
get ejemplo
VALUE ejemplo 0 14
systemadmin.es
END
quit
Connection closed by foreign host.

Podemos comprobar la replicación (la alta disponibilidad) matando al primero:

# jobs
[1]-  Running                 /usr/local/bin/memcached -u memcached -p 11211 -m 64 -x 127.0.0.1 -v &
[2]+  Running                 /usr/local/bin/memcached -u memcached -p 22322 -m 64 -x 127.0.0.1 -v &
# fg 1
/usr/local/bin/memcached -u memcached -p 11211 -m 64 -x 127.0.0.1 -v
^Creplication: cleanup start
replication: close
replication: cleanup complete
replication: close
replication: listen

Y intentando obtener los datos:

# telnet localhost 22322
Trying ::1...
Connected to localhost.
Escape character is '^]'.
get web
VALUE web 0 14
systemadmin.es
END
get ejemplo
VALUE ejemplo 0 14
systemadmin.es
END
quit
Connection closed by foreign host.

Es una forma cómoda de obtener una alta disponibilidad de los datos de memcached, pero evidentemente a costa de dividir por dos la memoria disponible para datos. Para repartir las queries de memcached en este escenario se puede hacer tanto a nivel de aplicación como mediante un balanceador como LVS.

Deja un comentario:

XHTML - Tags permitidos:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>