Комментарии 41
github.com/Negashev/keydb-cluster
В случае с sentinel существует дополнительный сетевой хоп, т.к. приложение сначала идет в sentinel-proxy, после чего уже попадает в сам редис, конечно же это касается тех приложений, который не поддерживает нативную работу с sentinel.
В таком случае по идее проблем не должно быть, т.к. там ассинхронные операции и напрямую влиять на клиентские get'ы и mget'ы не должны.
разработчики Redis упорно не хотят внедрять полноценную параллельность, упоминая, насколько это усложнит приложение и повысит накладные расходы
Ну вы наверное упорно не понимаете философию редис. Обвинять редис в том что он однопоточный, это всё равно что обвинять Си, в том что он компилируемый, Go в том что статически типизированный, а mysql в том что таблицы нужно декларировать, прежде чем использовать.
У одного из проектов мы столкнулись с тем, что команда разработки настроила крайне агрессивное кэширование данных из БД (PostgreSQL) через Redis
Могли бы запустить по одному редису на каждое ядро. При кэшировании, по ключу кэша, вычислять (например взять последние 3 бита от md5 ключа) в каком из редисов это будет храниться. Тогда бы ваша система выполняла свои функции вообще без межпроцессного/межпотокового взаимодействия, что было бы быстрее. Но вы взяли другой инструмент и теперь ваша система синхронизируется между потоками и переключает контекст там, где это не нужно.
Ну вы наверное упорно не понимаете философию редис. Обвинять редис в том что он однопоточный…
А вы точно дочитали до:
Не буду давать оценку тому или иному мнению.
? :-)
К сожалению мир не делится на белый и черный. Есть моменты когда мы можем бороться, есть — когда нет. Есть моменты когда бизнес может идти на встречу, а есть — когда физически нет таких возможностей. Мы стараемся идти на встречу при любом раскладе дел.
Вот эта статья — это не best practice [о чём явно в ней написано]. Это иллюстрация опытного эксперимента, какие тоже имеют место в жизни (в определённых случаях), даже если мы стремимся к лучшему. Реализуя его, стоит учитывать проблемы, помнить, что не это идеал, к которому надо идти, понимать, как всё-таки должно быть в перспективе.
Вот я сейчас использую redis-cluster. 16 физических шардов по три процесса на сервер по две реплики. Т.е. 32 сервера, 48 редисных шардов, 96 редисных процессов. И я в серьез подумываю про KeyDB, т.к. это позволит мне сэкономить гору процессорного времени. Почему? Да потому что на 48 шардов очень плохо работает пайплайнинг запросов. А он экономит цпу как на клиенте, так и в самом редисе. А с keydb у меня будет всего 16 шардов.
Останавливает меня только репликация: сейчас каждый редисный шард по 6GB, и мне приходится применять не тривиальную конфигурацию, чтобы редис физически был способен отреплицировать после рестарта реплики без отвала по достижению своих внутренних лимитов. Я сильно сомневаюсь, что KeyDB сможет отреплицировать 18GB.
И что за кейс где нужен пайплайнинг — это же не кэширование?
Будет. Оверхед от многопоточности в KeyDB — это взять мьютекс перед походом в хэш-мап, и отпустить после.
> И что за кейс где нужен пайплайнинг — это же не кэширование?
Как это «не кэширование»? У нас весь бэкенд шлёт до 2М запросов в секунду в редис именно за кешем. «не кэш» использования редиса у нас очень мало.
Просто наш коннектор умеет делать «прозрачный пайплайнинг», когда запросы из параллельных горутин в один сокет пишутся.
В них обычно условие для пайплайнинга — есть N команд, но на первые N-1 ответ не нужен срочно. А нужен только в конце.
Т.е. вот 4 команды
SET X 1
SET Y 2
GET W
GET Z
и нам ответ нужен только в конце — это W и Z. Нам не нужен W до этого момента и тем более результаты установки X, Y. В этом случае пайплайнинг позволяет послать 4 команды, а потом ждать ответа.
У вас же такого нет, просто из разных процессов всё идёт через один сокет. И в клиенте у вас конкурентность и на redis-server. А могло бы всё идти по разным сокетам и без конкурентности… В чём профит, непонятно. Разве что какие-то внутренние проблемы редиса с
большим кол-вом сокетов.
Да потому что на 48 шардов очень плохо работает пайплайнинг запросов. А он экономит цпу как на клиенте, так и в самом редисе
Т.е. 8 клиентов на 8 редис процессов могли бы идти по 8 сокетам. Все на разных ядрах.
А у вас 8 клиентов идут на 8 редис тредов через 1 сокет все в перемешку.
И профит в том что и клиент и сервер жрут меньше CPU. Непонятно…
Когда начнёте профилировать, поймёте: экономия цпу от 10% до 40%. Когда это экономится на клиенте, это не так может заметно. А вот когда в редисе, то очень чувствительно!
А у вас 8 клиентов идут на 8 редис тредов через 1 сокет все в перемешку.
«Клиентов» в одном процессе — десятки. Редисов всего 96. Если по вашей логике, то это 1000 сокетов с одного только процесса клиента. А тачек клиентов у нас тоже не один десяток.
Но и не мы разработчики той системы которую обслуживаем. А провести рефактор кода далеко не всегда возможно, и нам надо выкручиваться исходя из существующих вводных данных, а не того, чего хотелось бы в идеале.
Причем вы даже можете не подозревать о существовании нитки, а сторонняя библиотека внутри создаст нитку и будет ваши колбэки дергать из нее).
А разве функцию можно передать между потоками?
Это ж как надо расстреливать ноги, чтобы в nodejs нитка, о существовании которой я не подозреваю, дёргала "мои" колбеки?)
Ой да ладно. Проблемы с транзакциями существуют когда в одной транзакции трогается несколько ключей. Если же каждый раз щупается один ключ, то ни тебе дедлоков, ни тебе отката трагзакций. Все очень даже неплохо масштабируется, если правильно готовит.
Да, в редисе есть возможность использовать и что-то, что они называют транзакциями, и Lua процедуры. Но на практике этим пользуются невероятно редко.
Кстати, в KeyDB весь выигрыш только из распараллеливания сетевого взаимодействия. Вся работа с данными идет под глобальным локом.
Т.е.:
а) сетевое взаимодействие настолько накладно, что есть выигрыш от мношопоточности
б) типичная работа с данными настолько быстрая (в redis/keydb), что делать ее под глобальным локом не больно. А значит нет дедлоков и откатов транзакций.
в) конечно, если поставить keydb на 32 ядерную машину, проблемы от глобального лока начнутся. Так что им есть куда расти.
Ну как так «невероятно редко». У нас например невероятно часто. Это же зависит от кейса — если кэш, то они не нужны. Если хранение данных, то нужны «часто».
Храните данные в Redis?… у вас стальные яйца, я вам скажу. Зная, как работает Redis, я бы не стал в нём ни чего хранить.
Если вам нужно inMemory, посмотрите хотя бы в сторону Tarantool. Он намного надёжнее в плане сохранности. А так же гибче. И вряд ли медленнее.
у редиса два механизма записи на диск — снапшоты и AOF. не вижу повода не хранить там даже важные данные.
Т.е. любые данные, которые вроде и не хотелось бы потерять, но если потеряются, то и хрен с ними. Да, такое можно.
> у редиса два механизма записи на диск — снапшоты и AOF. не вижу повода не хранить там даже важные данные.
А я не вижу повода хранить:
— AOF и snapshot к сожалению друг о друге не знают.
— snapshot делается редко. Его рассматривать вообще нет смысла.
— запись в AOF идёт в том же треде. Если диск притормаживается (реплика подключилась), то всё встаёт колом. И ЧТЕНИЕ ТОЖЕ!
— а диск в том числе подтормаживает, когда AOF файл захотел сделать себе rewrite. Ну или если реплика приконнектилась.
— AOF не содержит номера команд. Потому Redis не может его использовать для наливки слейва. И слейв не может его использовать, если вдруг рестартанулся. Единственный выход у Редиса — откладывать новый снапшот (здравствуйте тормоза диска) и копить изменения в памяти. Чтобы отреплицировать 6ГБ инстанс мне приходится в настройках держать `client-output-buffer-limit replica 0 0 0` и `repl-backlog-size 200mb`.
Для сравнения, Tarantool:
— снапшоты и xlog файлы образуют единый механизм,
— xlog файлы содержат номер каждой операции
— реплика читает свой снапшот, проигрывает свои xlog и только после этого коннектится к мастеру и читает с последней операции
— мастер сперва шлёт данные с xlog файлов с нужного места (переслав перед этим уже готовый снапшота, если реплика новая или слишком отстала), и только когда реплика догоняет, переключается на inmemory посылку (емнип).
— данные в xlog пишутся в соседнем треде. Основной тред продолжает работу и спокойно обслуживает read запросы (и готовит к записи новые write запросы) даже если диск подтупил слегка.
А что я должен был понять?
А вот статистика по операции get в Redis:
А что подразумевается под «cpm», можно уточнить?
Что именно мешало в ней шардировать редис?
Но как всегда — на проде невозможно, кто же нам даст терзать прод в свою волю. А чтобы это воспроизвести не на проде — нужно поднимать идентичный тестовый стенд, на что конечно же нет ресурсов.
С хорошим pipelining редис может миллион rps на половинке ядра выдать.
На нормальной железке, redis упирается в одно ядро процессора.
Кто нибудь находил дашборд для графаны для keydb?
KeyDB как [потенциальная] замена Redis