Pull to refresh

Comments 31

Касательно части производительности. Вообще бенчмаркать редис в одну сессию относительно глупо. Redis имеет простой event-loop design и на деле при одном сокете будет каждый раз будет происходить context switch при вызове epoll_await. Как только мы увеличиваем кол-во сессий, даже просто в два раза (2 коннекта), у нас пропускная способность увеличится > 2 в два раза.

Пример (i7 930 2.8GHz):
root@tundra01h ~ # redis-benchmark -c 1 -n 100000 -q -t SET
SET: 53590.57 requests per second

root@tundra01h ~ # redis-benchmark -c 1 -n 100000 -q -t GET
GET: 54794.52 requests per second

root@tundra01h ~ # redis-benchmark -c 2 -n 100000 -q -t SET
SET: 127064.80 requests per second

root@tundra01h ~ # redis-benchmark -c 2 -n 100000 -q -t GET
GET: 136612.02 requests per second

root@tundra01h ~ # redis-benchmark -c 4 -n 100000 -q -t SET
SET: 144300.14 requests per second

root@tundra01h ~ # redis-benchmark -c 4 -n 100000 -q -t GET
GET: 141843.97 requests per second



Если кто-то может, побенчмаркайте gibson на нескольких сокетах.

По теме, ну хорошо, внутри там дерево, а не хеш-таблица. Чем это лучше и для каких use-case?:) По идее должно быть лучше на бооооооольшом количестве ключей, когда сравнивать хеши уже дорого, а по дереву пробежаться быстрей. Есть желающие побенчмаркать на заполненой памяти?:)
Чем это лучше и для каких use-case
Ну, это дает множественную замену…
По идее должно быть лучше на бооооооольшом количестве ключей
С чего бы? Для больших объемов длина хеша растет логарифмически, как и глубина дерева.
Я подумал что мета-информация ключей хранятся не в виде хеш-таблицы, а в виде дерева, а тут именно перезапись родительского ключа может заменить дочерние. Не так понял фичу:)
Из вашего сообщения я ничего не понял.
Впрочем, разобрались и ладно
Хеш-таблицы на больших объемах страдают или от коллизий или от (не) эффективности использования памяти.
По теме, ну хорошо, внутри там дерево, а не хеш-таблица. Чем это лучше и для каких use-case?:) По идее должно быть лучше на бооооооольшом количестве ключей, когда сравнивать хеши уже дорого, а по дереву пробежаться быстрей.

Ну откуда вы могли придумать такое? На получение одного ключа асимптотика дерева О(log N), а у хэш-таблицы О(1). Другое дело, что в случае с деревом появляется возможность работать с поддеревьями, в статье как раз пример про множественные get/set.

Основная проблема хэш-таблиц — это соответствие количества бакетов количеству ключей. При хорошем алгоритме хеширования хорошее отношение размера памяти к количеству коллизий достигается при load factor < 0.7. Если динамически изменять размер, то производительность на запись резко падает и становится не сильно лучше, чем у деревьев. При этом абсолютные цифры не важны, главное — load factor, то есть отношение количества ключей к количеству бакетов.
Кстати, а если не изменять размер, а построить хэш-таблицу, чтобы в каждой корзине данные хранились в виде не простого связанного списка, а чего-то другого (другой хэш-таблицы с другим размером или еще лучше — с другим принципом хэширования; дерева) — можно ли тогда достичь хорошей скорости?
Нередко бывает так, что на практике разницу между деревом и хэш-таблицей, когда они в памяти, будет видно только после добавления десятков, а то и сотен миллионов ключей. Если вкладывать хэш-таблицу в хэш-таблицу, то от load factor уйти не получится. Если дерево — то придётся балансировать: много бакетов — мелкие деревья — быстрый доступ, мало бакетов — большие деревья — дольше доступ. Будет быстрее или медленнее — зависит от многих параметров. Асимптотически хэш-таблица в хэш-таблице будет работать за константу, дерево в таблице — за логарифм уже.

Из преимуществ хэш-таблицы можно назвать независимость бакетов друг от друга, если конечно перебалансировку не делаете. То есть при добавлении любого ключа меняется только один бакет. Можно ставить по одному локу на бакет. При использовании деревьев почти всегда используют самобалансирующиеся деревья, при добавлении ключа может измениться до log N узлов дерева. То есть работа с деревом — только под локом на всё дерево.
есть неблокирующие алгоритмы для самобалансирующихся деревьев
Можно примеры, работающие на x86, в которых решена проблема ABA и не требуется специальный аллокатор?
не знаю насчет деталей, но вроде бы BTRFS использует подобный алгоритм
Вы со спинлоками точно не путаете?
Разработчик Gibson очень сетует на тему, что в redis-benchmark используется не multithreading, а multiplexing, что собственно не соответствует реальным условиям.
Чтобы не переходить на другую машину, попробуйте что-нибудь типа
for i in 1 2
do
    redis-benchmark -c 1 -n 100000 -q -t SET &
done

root@tundra01h ~ # for i in 1 2; do     redis-benchmark -c 1 -n 100000 -q -t SET & done
[1] 13193
[2] 13194
SET: 57045.07 requests per second

SET: 57012.54 requests per second


[1]-  Done                    redis-benchmark -c 1 -n 100000 -q -t SET
[2]+  Done                    redis-benchmark -c 1 -n 100000 -q -t SET


Угумс, чуть больше чем двукратный прирост, но не 127krps.

А знаете почему? Да потому что redis-benchmark написан тоже с использованием такого же event-loop и у него та же проблема. Запустив два одновременно мы избавились от тормозов в самом редисе, но context switch на epoll_wait в бенчмарках остался, и поэтому прирост маленький.

В моем тесте ускорились 2 event-loop, в redis и redis-benchmark. При нескольких сессиях ускоряются оба. В вашем же случае ускорился только redis, redis-benchmark как работал неэффективно на одной сессии, так и продолжает:)
проще написать собственный бенчмарк, протокол у редиса — простейший
или доработать существующий бенчмарк
Зачем дописывать, стандартный не плох, а есть и сторонние:)
Посмотрел документацию. посмотрел пример с хранением сессий пхп и кэша вордпресса. Все вроде очевидно и обычно. В чем соль? Или только производительность в синтетических тестах лучше?
Например, там есть такое:
mdel
Description: Delete keys verifying the given expression.
Parameters: key (string) The key prefix to use as expression.
Return value: Mixed The integer number of deleted items in case of success, FALSE in case of failure.

$gibson->mdel('f'); // Delete every f* key.

Мемкешд и редис не умеют так (редис, разве что, через консоль). А это в свою очередь позволяет удалять все значения, например, для измененной категории:

// Сохраняем страничку в кеше
$gibson->set('/foo/', 'bar');
// Меняем что-то там и кеширем
$gibson->set('/foo/', 'egg');
// Выносим каскадно все дочерние страницы из кеша
$gibson->mdel('/foo/');

«Delete every f* key.» — очень доходчиво, как по мне :)
Я только не понял, зачем сравнивать персистентный redis с заметно большим фунционалом, а не с банальным memcache'ом. Кроме того, нет сравнения производительности операций по префиксам, что нивелирует эффект от бенчмарков, оставляя пустое «Под мои задачи должна вписаться идеально».

Плюс есть специфически работающий лок, под который я сходу не могу придумать кейсов.
там из редис вытянуты необходимые исходники
Больше он конечно похож на memcached чем на redis, как я понял он не сохраняет базу на диск и восстанавливаться не умеет. Единственным плюсом перед memcached вижу блокировки, чего нехватает memcached. И тут возникает вопрос что делает другой клиент если кто-то поставил блокировку: он ждёт, он получает старое значение или он получает ошибку?

В драйвере для php нет pconnect(persistent connection)… А это значит каждая вновь запущенная php'шка будет задерживаться на открытии соединения от нескольким миллисекунд до 3 с лишним секунд. 3 секунды нужны для ожидания Syn пакета, который отправляется не ранее 3 секунд. Это происходит в моменты когда нагрузка на сервер внезапно возрастает по каким либо причинам и вместо того чтобы работать php'шки будут подвисать на коннекте к gibson на 3 сек, что недопустимо. Можно конечно через pfsockopen попробовать, но вот умеет ли gibson это?

Еще не плохо бы в мультигет запросах заиметь некий метаязык который бы позволил в одном запросе в случае хита получить ещё что-то с ключом зависимым от значения полученного ранее. Например записываешь список пользователей и при записи указываешь список зависимых ключей, а когда получаешь список из N пользователей и если такой список есть, сразу выдать ещё N значений с атрибутами пользователей. Экономия сотен микросекунд.
Автор, спасибо тебе за находку. Учитывая, что оно может обновлять TTL, удалять и менять значения по паттерну, можно проще и удобнее работать с кешем без необходимости заранее знать все ключи (для удаления, обновления). Ждем питоновскую библиотеку.
Объясните мне пожалуйста, тупому, чем он лучше Тарантула? В Тарантуле имеем всё то же самое, + совместимость с мемкешом по протоколу. Может тем, что у него меньше фич? Это иногда плюс. Но с другой стороны, драйвера для разных языков, поддержка дистрибутивов и платформ — это всё для Гибсона в зачаточном состоянии. Тарантул часто не используют именно потому, что недостаточная поддержка того или иного дистрибутива. Или community соберётся и всё сама напишет?

Да наверное ничем не лучше. А вам бы какой-нибудь tutorial или quick-start написать… Я лично раза 2 пытался к Tarantool подступиться, но бысто отказывался, т.к. не находил с чего начать.
Имею в виду, конечно же, не то, как его установить, а то, как работать с данными в нём. Имею в виду что-то вроде tarantool.org/tarantool_user_guide.html#data-and-persistence но побольше примеров. Желательно приближенных к реальности.
использую тарантул более года, реализовано два проекта (оба социальные игры),
принципиально доволен,
администрирование нормальное, саппорт вменяемый.

что касается инструкции — то мне кажется, что у команды разработчиков столько много идей, что они их реализовывать не успевают, так что руководство писать некому в маленькой команде :)

Ждем новых фич от тарантула!
Рад за вас.

Но необходимость Tutorial / Quick Start это не отменяет.
Мы покурили тут ваш комментарий, поняли что т.к. Тарантул по факту база данных + апп сервер, то проблема в отсутствии вменяемого пакет менеджера для наших модулей на Луа.

Для того, чтобы написать краткий туториал который будет работать не у гика, нужно чтобы всё делалось одной-двумя стандартными командами, типа apt-get install lua-module; sudo service tarantool restart

Сейчас тарантул может очень много, но для того чтобы от этого иметь профит надо шарить в Луа…

Будем пилить дальше, спасибо за коммент.
UFO just landed and posted this here
Cам являюсь пользователем Tokyo, использую его АПИ для создания собственного NoSQL хранилища.
Принципиально оно меня удовлетворяет, как хранилище с разными типами ключей TREE и HASH.
Другие АПИ (https://github.com/fmela/libdict) иногда валят проект сигфолтом.
Используется для хранения лайков и других счетчиков. Нагрузка на проект 5-7К запр в сек. в пике бывает 50К.
Sign up to leave a comment.

Articles