sql >> Databasteknik >  >> NoSQL >> Redis

Hur förbättrar jag Redis-serverns CPU-användning?

Jag tvivlar på att maximera CPU-användningen av Redis kommer att gynna din backend-design. Den rätta frågan är snarare om Redis är tillräckligt effektiv för att upprätthålla din genomströmning vid en given latens. Redis är en enkeltrådad server:vid 80 % CPU-förbrukning kommer latensen sannolikt att vara mycket dålig.

Jag föreslår att du mäter latens medan redis-benchmark arbetar för att se om det är acceptabelt för dina behov innan du försöker öka Redis CPU-förbrukning. Alternativet --latency för redis-cli kan användas för detta:

  • starta redis-server
  • prova redis-cli --latency, notera medelvärdet, stoppa det
  • i ett annat fönster, starta riktmärket och se till att det körs ett tag
  • prova redis-cli --latency, notera medelvärdet, stoppa det
  • stoppa riktmärket
  • jämför de två medelvärdena

Nu, om du verkligen vill öka Redis CPU-förbrukning, behöver du antingen ett effektivt klientprogram (som redis-benchmark), som kan hantera flera anslutningar samtidigt, antingen flera instanser av ditt klientprogram.

Lua är ett snabbt tolkat språk, men det är fortfarande ett tolkat språk. Det kommer att vara en eller två storleksordningar långsammare än C-koden. Redis är mycket snabbare på att analysera/generera sitt protokoll än lua-redis, så du kommer inte att kunna mätta Redis med en unik Lua-klient (förutom om du använder O(n) Redis-kommandon - se senare).

webdis är implementerat i C, med ett effektivt klientbibliotek, men måste analysera http/json-protokollen som råkar vara mer omfattande och komplexa än Redis-protokollet. Den förbrukar sannolikt mer CPU än Redis själv för de flesta operationer. Så återigen, du kommer inte att mätta Redis med en enda webdis-instans.

Här är några exempel för att mätta Redis med flera Lua-klienter.

Om det inte redan är gjort, föreslår jag att du tog en titt på Redis benchmark-sida först.

Om du kör ditt benchmark på samma ruta som Redis:

Nyckelpunkten är att dedikera en kärna till Redis och köra klientprogrammen på de andra kärnorna. På Linux kan du använda kommandot taskset för detta.

# 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

Lua-programmet bör använda pipelining för att maximera genomströmningen och minska systemaktiviteten.

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

På mitt system tar Lua-programmet mer än fyra gånger så mycket CPU som Redis, så du behöver mer än fyra kärnor för att mätta Redis med den här metoden (en låda med sex kärnor borde vara bra).

Om du kör ditt benchmark på en annan box än Redis:

Förutom om du kör på CPU-svälta virtuella maskiner, kommer flaskhalsen troligen att vara nätverket i så fall. Jag tror inte att du kan mätta Redis med något mindre än en 1 GbE-länk.

Se till att pipeline dina frågor så långt du kan (se det tidigare Lua-programmet) för att undvika flaskhalsen för nätverkslatens och minska kostnaderna för nätverksavbrott på CPU:n (fylla Ethernet-paket). Försök att köra Redis på en kärna som inte är bunden till nätverkskortet (och bearbetar nätverksavbrott). Du kan använda verktyg som htop för att kontrollera den sista punkten.

Försök att köra dina Lua-klienter på olika andra maskiner i nätverket om du kan. Återigen kommer du att behöva ett stort antal Lua-klienter för att mätta Redis (6-10 borde vara bra).

I vissa fall räcker det med en unik Lua-process:

Nu är det möjligt att mätta Redis med en enda Lua-klient om varje fråga är tillräckligt dyr. Här är ett exempel:

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

Detta program fyller en lista med 1M objekt och använder sedan lrange-kommandon för att hämta 10 objekt från mitten av listan (värsta fall för Redis). Så varje gång en fråga exekveras, skannas 500 000 objekt av servern. Eftersom endast 10 artiklar returneras är de snabba att analysera av lua-redis som inte kommer att förbruka CPU. I den här situationen kommer all CPU-förbrukning att ligga på serversidan.

Sluta ord

Det finns förmodligen snabbare Redis-klienter än redis-lua:

  • https://github.com/agladysh/lua-hiredis (baserat på hiredis)
  • https://github.com/agladysh/ljffi-hiredis (baserat på hirdis, med luajit FFI)

Du kanske vill prova dem.




  1. Klona databas i Mongodb mellan värdar med noddrivrutin

  2. Kan Redis 6 dra fördel av flerkärniga processorer?

  3. Vad är Mongoose (Nodejs) pluraliseringsregler?

  4. Använda Redis för köer för flera Laravel-applikationer på en enda server