sql >> Base de Datos >  >> NoSQL >> Redis

¿Cómo mejorar el uso de la CPU del servidor Redis?

Dudo que maximizar el uso de CPU de Redis beneficie su diseño de back-end. La pregunta correcta es si Redis es lo suficientemente eficiente como para mantener su rendimiento en una latencia determinada. Redis es un servidor de subproceso único:con un consumo de CPU del 80 %, es probable que la latencia sea muy mala.

Le sugiero que mida la latencia mientras redis-benchmark está funcionando para ver si es aceptable para sus necesidades antes de intentar aumentar el consumo de CPU de Redis. La opción --latency de redis-cli se puede usar para esto:

  • iniciar servidor redis
  • pruebe redis-cli --latency, anote el valor promedio, deténgalo
  • en otra ventana, inicie el punto de referencia y asegúrese de que se ejecute durante un tiempo
  • pruebe redis-cli --latency, anote el valor promedio, deténgalo
  • detener el punto de referencia
  • compare los dos valores promedio

Ahora, si realmente desea aumentar el consumo de CPU de Redis, necesita un programa cliente eficiente (como redis-benchmark), capaz de manejar varias conexiones al mismo tiempo, o varias instancias de su programa cliente.

Lua es un lenguaje interpretado rápido, pero sigue siendo un lenguaje interpretado. Será uno o dos órdenes de magnitud más lento que el código C. Redis es mucho más rápido para analizar/generar su protocolo que lua-redis, por lo que no podrá saturar Redis con un cliente Lua único (excepto si usa los comandos O(n) Redis; vea más adelante).

webdis está implementado en C, con una biblioteca de cliente eficiente, pero tiene que analizar los protocolos http/json que resultan ser más detallados y complejos que el protocolo Redis. Es probable que consuma más CPU que el propio Redis para la mayoría de las operaciones. De nuevo, no saturará Redis con una sola instancia de webdis.

Estos son algunos ejemplos para saturar Redis con múltiples clientes Lua.

Si aún no lo ha hecho, le sugiero que primero eche un vistazo a la página de referencia de Redis.

Si ejecuta su punto de referencia en el mismo cuadro que Redis:

El punto clave es dedicar un núcleo a Redis y ejecutar los programas cliente en los otros núcleos. En Linux, puede usar el comando taskset para esto.

# Start Redis on core 0
taskset -c 0 redis-server redis.conf

# Start Lua programs on the other cores
for x in `seq 1 10` ; do taskset -c 1,2,3 luajit example.lua & done

El programa Lua debe usar canalización para maximizar el rendimiento y reducir la actividad del sistema.

local redis = require 'redis'
local client = redis.connect('127.0.0.1', 6379)
for i=1,1000000 do
    local replies = client:pipeline(function(p)
    for j=1,1000 do
            local key = 'counter:'..tostring(j)
            p:incrby(key,1)
        end
    end)
end

En mi sistema, el programa Lua requiere más de 4 veces la CPU de Redis, por lo que necesita más de 4 núcleos para saturar Redis con este método (una caja de 6 núcleos debería estar bien).

Si ejecuta su punto de referencia en un cuadro diferente al de Redis:

Excepto si se ejecuta en máquinas virtuales hambrientas de CPU, el cuello de botella probablemente será la red en ese caso. No creo que puedas saturar Redis con nada menos que un enlace de 1 GbE.

Asegúrese de canalizar sus consultas en la medida de lo posible (consulte el programa Lua anterior) para evitar el cuello de botella de latencia de red y reducir el costo de las interrupciones de red en la CPU (llenar paquetes de Ethernet). Intente ejecutar Redis en un núcleo que no esté vinculado a la tarjeta de red (y procese las interrupciones de la red). Puedes usar herramientas como htop para comprobar este último punto.

Intente ejecutar sus clientes Lua en varias otras máquinas de la red si puede. Una vez más, necesitará una buena cantidad de clientes de Lua para saturar Redis (de 6 a 10 debería estar bien).

En algunos casos, un proceso Lua único es suficiente:

Ahora, es posible saturar Redis con un solo cliente Lua si cada consulta es lo suficientemente costosa. Aquí hay un ejemplo:

local redis = require 'redis'
local client = redis.connect('127.0.0.1', 6379)

for i=1,1000 do
    local replies = client:pipeline(function(p)
        for j=1,1000 do
            p:rpush("toto",i*1000+j)
        end
    end)
end

N = 500000
for i=1,100000 do
    local replies = client:pipeline(function(p)
        for j=1,10 do
            p:lrange("toto",N, N+10)
        end
    end)
end

Este programa completa una lista con 1 millón de elementos y luego usa comandos lrange para obtener 10 elementos del medio de la lista (el peor de los casos para Redis). Por lo tanto, cada vez que se ejecuta una consulta, el servidor escanea 500 000 elementos. Debido a que solo se devuelven 10 elementos, lua-redis los analiza rápidamente y no consume CPU. En esta situación, todo el consumo de CPU estará en el lado del servidor.

Palabras finales

Probablemente haya clientes de Redis más rápidos que redis-lua:

  • https://github.com/agladysh/lua-hiredis (basado en contratadas)
  • https://github.com/agladysh/ljffi-hiredis (basado en contratadas, usando luajit FFI)

Es posible que desee probarlos.