LINUX.ORG.RU

Самые быстрые способы массовой записи в Redis и массового чтения из Redis

 ,


0

3

Предлагаю помериться таймингами и сравнить эффективность алгоритмов записи/чтения применительно к Redis и языку Perl

Задача следующая:

Сначала как можно быстрее записать в пустую базу Redis N объектов (N для отсечки 2000 штук), а потом как можно быстрее их оттуда считать.

Объекты должны быть хешами, содержащими 2 поля: 1 текстовое поле длиной до 15-ти символов и одно числовое поле, содержащее произвольное число от 0 до N-1.

Для записи и чтения можно использовать разные пакеты Perl.

Интересно выяснить, какой модуль для работы с Redis в Perl быстрее всех и какая техника записи/чтения самая эффективная. Я уже делал подобный тест, но вполне вероятно, что мой путь его выполнения был неоптимальным.

P.S. Если есть желание, можно для сравнения накатать тесты и на других ___интерпретируемых___ языках программирования.

★★★★★

Ставлю на

perl -wE 'map{printf "SET Key%i Value%i\n",$_,$_} 1..2000' | redis-cli --pipe

Если серьёзно, то redis почти все используют как кеш, а батчевые инсерты это не типичный юзкейс для кеша.

disarmer ★★★
()
Последнее исправление: disarmer (всего исправлений: 1)
Ответ на: комментарий от disarmer

По-моему вполне типичный как раз: можно раскидать объекты, героическими усилиями собранные каверзными запросами из тормозной реляционной СУБД типа MySQL. При этом будем иметь не очень удобную для запросов по объектам структуру в Redis, но зато удобную для скатертной сборки из них хеша.

У меня, например, полно задач с хранением графов с выраженной древовидной структурой (не совсем просто граф-дерево, поскольку есть интерлинки между ветками). Как их сложить в кеш, если может быть запрошена любая ветка? Хранить в кеше и эту ветку, и ту, что отличается от неё единственным узлом (родительскую или дочернюю) - ИМХО, это просто не вариант, да и парсить такое что JSON'ом, что BJSON'ом, что CBOR'ом - дикий геморрой. А вот просто собрать объекты, объединив их линкующими полями типа parent или children - как нефиг делать. У меня на загруженной системе Perl'ом с его убогой принципиальной нераспараллеливаемостью (интерпретатор же, что с него взять) - дерево из 28000 с лишним объектов собирается за ~5 секунд. То же самое собирается из MySQL минимум в 3 раза дольше - и это при том, что дерево, хранимое в Redis, содержит массу уже вычисленных полей, а в MySQL всего этого нет, и вычисления заняли бы ещё немало времени.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от disarmer
#!/usr/bin/perl
use feature 'say';
use Time::HiRes qw(time);
use Redis;
use Data::Dumper;

my $objsN=shift || die 'You must specify number of objects to insert/read';

my $r=Redis->new;
$r->flushdb;

my $start=time;

$r->multi;
$r->hmset($_, 'value'=>$_, 'name'=>'node#'.$_) for 0..(abs($objsN)-1);
$r->exec(sub { });

$r->wait_all_responses;

say 'Exec time: ', time()-$start, ' sec.';

На моём маломощном ноутбуке вставка 50000 записей занимает в среднем 4.1 сек

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

А вот так уже 2.4-2.6 секунды. Почувствуйте разницу: multi не есть столь хорошо, как это могло бы показаться.

$r->hmset($_, 'value'=>$_, 'name'=>'node#'.$_, sub {}) for 0..(abs($objsN)-1);

$r->wait_all_responses;

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Асинхронная модификация hmset в 1-м примере даёт уже 2.7-2.8 сек, что всё равно хуже самого прямолинейного варианта без multi/exec.

DRVTiny ★★★★★
() автор топика

Привет, правильный способ готовки редиса, это запустить N экземляров на одной машине(редис однопоточный) и реализовать определённую схему разнесения ключей по хешам(можно попробовать redis cluster, но сам я не пробовал), тогда с клиента можно писать и читать в параллели

anonymous
()
Ответ на: комментарий от DRVTiny

А за сколько отрабатывает аналогичная вставка через redis-cli --pipe? Хотя бы будет понятна максимальная скорость самого redis

disarmer ★★★
()
Ответ на: комментарий от disarmer

У меня так вообще не работает. Пишет:

ERR unknown command 'ET'
ERR unknown command 'ET'
ERR unknown command 'ET'
ERR unknown command 'ET'
ERR unknown command 'ET'
ERR unknown command 'ET'
ERR unknown command 'ET'
ERR unknown command '2'
ERR unknown command '$4'
ERR wrong number of arguments for 'echo' command
ERR unknown command '$20'

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от disarmer

Через твой скрипт миллион записей вставляется за ~82s. Причём сам скрипт в 2-3 раза больше чем redis-server cpu жрёт

Через nc за 5.49s:

perl -wE 'for(1..1000000){printf "SET Key%i Value%i\r\n",$_,$_};printf "QUIT\r\n"' | nc localhost 6379 > /dev/null

disarmer ★★★
()
Ответ на: комментарий от DRVTiny

Даже если делать HMSET, реально быстро вставляет данные, 6 сек у меня на 1e+6 записей. Круто... Интересно, если через сокет засылать штатными средствами Perl - всё будет намного хуже «из-за того, что perl»? Надо проверить...

DRVTiny ★★★★★
() автор топика
Последнее исправление: DRVTiny (всего исправлений: 1)
Ответ на: комментарий от disarmer

Ты ещё «производительность» Mojo::Redis2 не видел... это просто нечто, на порядок ниже скорости обычного модуля Redis.

DRVTiny ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.