Memcached vs lua+redis en nginx

Pues para terminar el post anterior, he configurado el nginx para que recogiera un dato de un memcached.

  location /memcahed {
        set            $memcached_key "data";
        memcached_pass unix:/var/run/memcached/memcached.sock;  #was localhost:11211;
    }

Y esto lo comparamos con el programa anterior en lua y tambien con un fichero vacio y con una respuesta vacia

    location /trivial {
           return 200 "Hola";
    }

Y bueno, el resultado no esta muy a favor de memcached. Basicamente, se satura y empieza a dar errores 502

for c in $(seq 10 10 1000); do ./go/bin/go-wrk -T 50000 -d 30 -c $c  http://.../memcahed | grep -E "(Requests/sec|Errors)" | tr -d  \\n; echo "   "$c; done
Requests/sec:		15862.64Number of Errors:	0   10
Requests/sec:		21499.75Number of Errors:	0   20
Requests/sec:		13896.68Number of Errors:	0   30
Requests/sec:		21485.56Number of Errors:	0   40
Requests/sec:		27212.85Number of Errors:	0   50
Requests/sec:		29213.32Number of Errors:	0   60
Requests/sec:		29714.41Number of Errors:	0   70
Requests/sec:		30107.10Number of Errors:	0   80
Requests/sec:		31174.87Number of Errors:	0   90
Requests/sec:		32520.20Number of Errors:	0   100
Requests/sec:		33842.69Number of Errors:	0   110
Requests/sec:		33592.75Number of Errors:	0   120
Requests/sec:		34786.32Number of Errors:	0   130
Requests/sec:		35004.92Number of Errors:	205   140
Requests/sec:		35355.53Number of Errors:	3411   150
Requests/sec:		36148.58Number of Errors:	1857   160
Requests/sec:		35144.53Number of Errors:	12578   170
Requests/sec:		34960.10Number of Errors:	10287   180

Y no tiene mucho arreglo, por mas que lancemos el memcached con esteroides

/usr/bin/memcached -t 128 -b 65536 -R 400 -m 64 -u memcache -s /var/run/memcached/memcached.sock -a 777 -c 1000000

Tampoco sirve de mucho ponerlo en un server block porque aunque permita levantar otros daemon de backup a cambio ya hay una perdida de velocidad apreciable por el mero hecho de activar el bloque. Quizas un memcache por cada worker podria dar alguna ganancia, pero por el mismo argumento podria duplicarse el numero de servicios de redis.

Por otro lado el programita en lua que puse en el post anterior aguanta bien el ritmo

for c in $(seq 10 10 1000); do ./go/bin/go-wrk -T 50000 -d 30 -c $c  http://193.146.116.204/luaRedis | grep -E "(Requests/sec|Errors)" | tr -d  \\n; echo "   "$c; done
Requests/sec:		15773.60Number of Errors:	0   10
Requests/sec:		22807.76Number of Errors:	0   20
Requests/sec:		25335.90Number of Errors:	0   30
Requests/sec:		32562.28Number of Errors:	0   40
Requests/sec:		34011.02Number of Errors:	0   50
Requests/sec:		33919.57Number of Errors:	0   60
Requests/sec:		32650.17Number of Errors:	0   70
Requests/sec:		33653.12Number of Errors:	0   80
Requests/sec:		33569.45Number of Errors:	0   90
Requests/sec:		35459.76Number of Errors:	0   100
Requests/sec:		34919.97Number of Errors:	0   110
Requests/sec:		39005.47Number of Errors:	0   120
Requests/sec:		39933.50Number of Errors:	0   130
Requests/sec:		36491.90Number of Errors:	0   140
Requests/sec:		36317.62Number of Errors:	0   150
Requests/sec:		38892.25Number of Errors:	0   160
Requests/sec:		41772.89Number of Errors:	0   170
Requests/sec:		40586.04Number of Errors:	0   180
...
Requests/sec:		45014.77Number of Errors:	0   400
Requests/sec:		44446.85Number of Errors:	0   500
Requests/sec:		43553.99Number of Errors:	0   600

Hasta llegar a unas 45000 requests por segundo. En las mismas condiciones (recordemos, dos hyperthreads o VCPUs para el nginx) la respuesta trivial puede subir a 70000 rps y la lectura de un fichero a 60000-70000 tambien, segun como vayan los caches. Es un poco desconcertante que siga siendo mas eficaz escribir un mensaje corto en un fichero que meterlo en un clave-valor; supongo que la situacion cambia si hay demasiados ficheros en un directorio. Pero si lo que tenemos son mil o diez mil usuarios haciendo presion por culpa de un polling, no deja de ser una solucion valida simplemente ¡¡¡ir respondiendo desde diez mil ficheros!!!. Si no fuera por la falta de redundancia, claro.

Ah ¿y que pasa con la solucion de usar una aplicacion en Rack sobre puma? Pues bueno, en las mismas condiciones de benchmark, atacando a redis y sin contar el esfuerzo de parsear la clave, sale por unas 6500 requests por segundo. Habria que ver cual de los dos servidores, si puma o nginx, reaccionaria mejor en el caso de querer usar estas respuestas en long polling en vez de para un poll intensivo. Pero eso es otro post.

One Comment

  1. Una notica… los errores iniciales de conexion y envio del dato a veces se arreglan dando uno o dos intentos mas, lo malo es que esos intentos van duplicandose en el tiempo, asi que tampoco nos valen de mucho en una prueba de carga intensiva. En cualquier caso, se puede intentar:
    echo 8 > /proc/sys/net/ipv4/tcp_synack_retries
    echo 8 > /proc/sys/net/ipv4/tcp_syn_retries

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.