Redis
 sql >> Base de Dados >  >> NoSQL >> Redis

Como melhorar o uso da CPU do servidor Redis?


Duvido que maximizar o uso da CPU do Redis beneficie seu design de back-end. A pergunta certa é se o Redis é eficiente o suficiente para sustentar sua taxa de transferência em uma determinada latência. O Redis é um servidor de thread único:com 80% de consumo de CPU, a latência provavelmente será muito ruim.

Sugiro que você meça a latência enquanto o redis-benchmark está funcionando para ver se é aceitável para suas necessidades antes de tentar aumentar o consumo de CPU do Redis. A opção --latency do redis-cli pode ser usada para isso:
  • iniciar servidor redis
  • tente redis-cli --latency, observe o valor médio, pare com isso
  • em outra janela, inicie o comparativo de mercado e certifique-se de que ele seja executado por um tempo
  • tente redis-cli --latency, observe o valor médio, pare com isso
  • parar o benchmark
  • compare os dois valores médios

Agora, se você realmente deseja aumentar o consumo de CPU do Redis, você precisa de um programa cliente eficiente (como redis-benchmark), capaz de lidar com várias conexões simultaneamente, ou várias instâncias do seu programa cliente.

Lua é uma linguagem interpretada rápida, mas ainda é uma linguagem interpretada. Será uma ou duas ordens de magnitude mais lenta que o código C. O Redis é muito mais rápido em analisar/gerar seu protocolo do que lua-redis, então você não poderá saturar o Redis com um cliente Lua exclusivo (exceto se você usar comandos O(n) Redis - veja mais adiante).

O webdis é implementado em C, com uma biblioteca cliente eficiente, mas precisa analisar os protocolos http/json que são mais detalhados e complexos que o protocolo Redis. Provavelmente consome mais CPU do que o próprio Redis para a maioria das operações. Então, novamente, você não saturará o Redis com uma única instância do webdis.

Aqui estão alguns exemplos para saturar o Redis com vários clientes Lua.

Se ainda não estiver feito, sugiro que você dê uma olhada na página de benchmark Redis primeiro.

Se você executar seu comparativo de mercado na mesma caixa que o Redis:

O ponto-chave é dedicar um núcleo ao Redis e executar os programas clientes nos outros núcleos. No Linux, você pode usar o comando taskset para isso.
# 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

O programa Lua deve usar pipelining para maximizar o rendimento e reduzir a atividade do 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

No meu sistema, o programa Lua consome mais de 4 vezes a CPU do Redis, então você precisa de mais de 4 núcleos para saturar o Redis com este método (uma caixa de 6 núcleos deve ser suficiente).

Se você executar seu comparativo de mercado em uma caixa diferente do Redis:

Exceto se você executar em máquinas virtuais com falta de CPU, o gargalo provavelmente será a rede nesse caso. Não acho que você possa saturar o Redis com menos de um link de 1 GbE.

Certifique-se de canalizar suas consultas o máximo que puder (veja o programa Lua anterior) para evitar o gargalo de latência de rede e reduzir o custo de interrupções de rede na CPU (preenchendo pacotes ethernet). Tente executar o Redis em um núcleo que não esteja vinculado à placa de rede (e processe interrupções de rede). Você pode usar ferramentas como htop para verificar este último ponto.

Tente executar seus clientes Lua em várias outras máquinas da rede, se puder. Novamente, você precisará de um bom número de clientes Lua para saturar o Redis (6-10 deve ser bom).

Em alguns casos, um processo Lua exclusivo é suficiente:

Agora, é possível saturar o Redis com um único cliente Lua se cada consulta for cara o suficiente. Aqui está um exemplo:
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 preenche uma lista com 1 milhão de itens e, em seguida, usa comandos lrange para buscar 10 itens do meio da lista (pior caso para Redis). Assim, cada vez que uma consulta é executada, 500 mil itens são verificados pelo servidor. Como apenas 10 itens são retornados, eles são rápidos para analisar por lua-redis que não consumirá CPU. Nesta situação, todo o consumo de CPU estará no lado do servidor.

Palavras finais

Provavelmente existem clientes Redis mais rápidos que redis-lua:
  • https://github.com/agladysh/lua-hiredis (com base em contratados)
  • https://github.com/agladysh/ljffi-hiredis (baseado em contractis, usando luajit FFI)

Você pode querer experimentá-los.