Съмнявам се, че максимизирането на използването на процесора на Redis ще бъде от полза за вашия бекенд дизайн. Правилният въпрос е по-скоро дали Redis е достатъчно ефективен, за да поддържа вашата пропускателна способност при дадена латентност. Redis е еднонишков сървър:при 80% консумация на процесора латентността вероятно ще бъде много лоша.
Предлагам ви да измервате латентността, докато redis-benchmark работи, за да видите дали е приемливо за вашите нужди, преди да се опитате да увеличите консумацията на Redis CPU. Опцията --latency на redis-cli може да се използва за това:
- стартирайте redis-сървър
- опитайте redis-cli --latency, обърнете внимание на средната стойност, спрете го
- в друг прозорец стартирайте бенчмарка и се уверете, че работи известно време
- опитайте redis-cli --latency, обърнете внимание на средната стойност, спрете го
- спрете бенчмарка
- сравнете двете средни стойности
Сега, ако наистина искате да увеличите консумацията на Redis CPU, имате нужда или от ефективна клиентска програма (като redis-benchmark), която може да обработва множество връзки едновременно, или няколко екземпляра на вашата клиентска програма.
Lua е бързо интерпретиран език, но все пак е интерпретиран език. Той ще бъде с един или два порядъка по-бавен от C кода. Redis е много по-бърз при анализиране/генериране на своя протокол от lua-redis, така че няма да можете да наситите Redis с уникален клиент на Lua (освен ако използвате O(n) команди Redis – вижте по-късно).
webdis е внедрен в C, с ефективна клиентска библиотека, но трябва да анализира http/json протоколите, които се оказват по-подробни и сложни от протокола Redis. Вероятно консумира повече CPU от самия Redis за повечето операции. Така че отново няма да наситите Redis с един екземпляр на webdis.
Ето няколко примера за насищане на Redis с множество Lua клиенти.
Ако все още не е направено, предлагам първо да разгледате страницата за сравнителен анализ на Redis.
Ако стартирате своя бенчмарк в същото поле като Redis:
Ключовият момент е да посветите ядрото на Redis и да стартирате клиентските програми на другите ядра. В Linux можете да използвате командата taskset за това.
# 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 трябва да използва конвейер, за да увеличи максимално пропускателната способност и да намали системната активност.
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
В моята система програмата Lua заема повече от 4 пъти CPU от Redis, така че имате нужда от повече от 4 ядра, за да наситите Redis с този метод (кутия с 6 ядра трябва да е добре).
Ако стартирате своя бенчмарк в кутия, различна от Redis:
Освен ако работите на виртуални машини с недостатъчен процесор, тясното място вероятно ще бъде мрежата в този случай. Не мисля, че можете да наситите Redis с нещо по-малко от 1 GbE връзка.
Уверете се, че сте изпълнили заявките си, доколкото можете (вижте предишната програма Lua), за да избегнете тесното място на мрежовата латентност и да намалите цената на мрежовите прекъсвания на процесора (запълване на Ethernet пакети). Опитайте да стартирате Redis на ядро, което не е свързано с мрежовата карта (и обработва прекъсвания на мрежата). Можете да използвате инструменти като htop, за да проверите тази последна точка.
Опитайте се да стартирате вашите Lua клиенти на различни други машини в мрежата, ако можете. Отново ще ви трябва голям брой клиенти на Lua, за да наситите Redis (6-10 трябва да са добре).
В някои случаи е достатъчен уникален процес на Lua:
Сега е възможно да наситите Redis с един клиент на Lua, ако всяка заявка е достатъчно скъпа. Ето един пример:
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
Тази програма попълва списък с 1M елемента и след това използва команди lrange, за да извлече 10 елемента от средата на списъка (най-лошият случай за Redis). Така че всеки път, когато се изпълни заявка, 500K елемента се сканират от сървъра. Тъй като се връщат само 10 елемента, те се анализират бързо от lua-redis, което няма да изразходва процесора. В тази ситуация цялото потребление на процесора ще бъде от страна на сървъра.
Последни думи
Вероятно има по-бързи клиенти на Redis от redis-lua:
- https://github.com/agladysh/lua-hiredis (базирано на hiredis)
- https://github.com/agladysh/ljffi-hiredis (базирано на hiredis, с помощта на luajit FFI)
Може да искате да ги опитате.