Как стать автором
Обновить

Комментарии 40

А Helm chart где-нибудь можно увидеть? Хотелось бы нормальный master-master — насколько я понимаю ни в Redis, ни в Redis-HA чартах такого нет сейчас.
Мы не публиковали его нигде, там в целом ничего хитрого. Если есть реальная потребность — могу соорудить.
Больше — не меньше. Я сам сейчас буду пилить (или воровать у китайцев) redis-cluster, поэтому неплохо было бы посмотреть на уже имеющиеся варианты. Буду признателен.
Кстати, скоро (постараемся на следующей неделе) у нас будет статья про наш опыт с одним K8s-оператором для Redis.
Видел сегодня, когда пытался найти решение на гитхабе.
Уточните, как кластерный редис (с сентинелом [который давно уже не актуален], либо нативный кластер) добавляет дополнительных задержек?
К сожалению у нас нет адекватного решения для redis cluster в кубах, поэтому пока используется sentinel.
В случае с sentinel существует дополнительный сетевой хоп, т.к. приложение сначала идет в sentinel-proxy, после чего уже попадает в сам редис, конечно же это касается тех приложений, который не поддерживает нативную работу с sentinel.
В таком случае по идее проблем не должно быть, т.к. там ассинхронные операции и напрямую влиять на клиентские get'ы и mget'ы не должны.

Думаю, либо ваш коннектор не умеет сам redis-sentinel, либо вы не догадались его приготовить.


Если коннектор умеет redis-sentinel, он будет ходить напрямую, без proxy.

разработчики Redis упорно не хотят внедрять полноценную параллельность, упоминая, насколько это усложнит приложение и повысит накладные расходы

Ну вы наверное упорно не понимаете философию редис. Обвинять редис в том что он однопоточный, это всё равно что обвинять Си, в том что он компилируемый, Go в том что статически типизированный, а mysql в том что таблицы нужно декларировать, прежде чем использовать.

У одного из проектов мы столкнулись с тем, что команда разработки настроила крайне агрессивное кэширование данных из БД (PostgreSQL) через Redis

Могли бы запустить по одному редису на каждое ядро. При кэшировании, по ключу кэша, вычислять (например взять последние 3 бита от md5 ключа) в каком из редисов это будет храниться. Тогда бы ваша система выполняла свои функции вообще без межпроцессного/межпотокового взаимодействия, что было бы быстрее. Но вы взяли другой инструмент и теперь ваша система синхронизируется между потоками и переключает контекст там, где это не нужно.
Ну вы наверное упорно не понимаете философию редис. Обвинять редис в том что он однопоточный…

А вы точно дочитали до:

Не буду давать оценку тому или иному мнению.

? :-)
Посыпались минусы, но я лишь хотел указать, что в статье нет обвинений. Есть указания на разные мнения и пути. И нет утверждений, что этот путь — правильный. Он просто есть, и раз для его реализации появился полноценный продукт, на него есть объективный спрос.
Т.е. вы героически воткнули костыль, вместо того, чтобы бороться с невежеством разработки на проекте? И эти люди говорят про DevOps как методологию и отсутствие «колодцев» между командами, ха.
Вы же понимаете насколько это упрощенно и однобоко звучит? :)
К сожалению мир не делится на белый и черный. Есть моменты когда мы можем бороться, есть — когда нет. Есть моменты когда бизнес может идти на встречу, а есть — когда физически нет таких возможностей. Мы стараемся идти на встречу при любом раскладе дел.
Эти люди всё-таки живут в реальном мире. Обратите внимание, что статья сознательно не добавлена в хаб «DevOps». Нас даже иногда критикуют за то, что мы в своих статьях/докладах часто рассказываем про какую-то мифическую идеальную инфраструктуру и сопутствующие процессы. Мол, всё это круто и красиво, но в жизни обычно по-другому.

Вот эта статья — это не best practice [о чём явно в ней написано]. Это иллюстрация опытного эксперимента, какие тоже имеют место в жизни (в определённых случаях), даже если мы стремимся к лучшему. Реализуя его, стоит учитывать проблемы, помнить, что не это идеал, к которому надо идти, понимать, как всё-таки должно быть в перспективе.

Вот я сейчас использую redis-cluster. 16 физических шардов по три процесса на сервер по две реплики. Т.е. 32 сервера, 48 редисных шардов, 96 редисных процессов. И я в серьез подумываю про KeyDB, т.к. это позволит мне сэкономить гору процессорного времени. Почему? Да потому что на 48 шардов очень плохо работает пайплайнинг запросов. А он экономит цпу как на клиенте, так и в самом редисе. А с keydb у меня будет всего 16 шардов.


Останавливает меня только репликация: сейчас каждый редисный шард по 6GB, и мне приходится применять не тривиальную конфигурацию, чтобы редис физически был способен отреплицировать после рестарта реплики без отвала по достижению своих внутренних лимитов. Я сильно сомневаюсь, что KeyDB сможет отреплицировать 18GB.

Про пайплайнинг замечание здравое. Но что-то у меня сомнения что KeyDB с оверхедом от многопоточности будет быстрее чем редис с оверхедом от отсутствия пайплайнинга. Или будет?
И что за кейс где нужен пайплайнинг — это же не кэширование?
> KeyDB с оверхедом от многопоточности будет быстрее чем редис с оверхедом от отсутствия пайплайнинга. Или будет?

Будет. Оверхед от многопоточности в 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 редис процессов могли бы идти по 8 сокетам. Все на разных ядрах.
А у вас 8 клиентов идут на 8 редис тредов через 1 сокет все в перемешку.

«Клиентов» в одном процессе — десятки. Редисов всего 96. Если по вашей логике, то это 1000 сокетов с одного только процесса клиента. А тачек клиентов у нас тоже не один десяток.
НЛО прилетело и опубликовало эту надпись здесь
И мы не спорим с этим! :)
Но и не мы разработчики той системы которую обслуживаем. А провести рефактор кода далеко не всегда возможно, и нам надо выкручиваться исходя из существующих вводных данных, а не того, чего хотелось бы в идеале.
Причем вы даже можете не подозревать о существовании нитки, а сторонняя библиотека внутри создаст нитку и будет ваши колбэки дергать из нее).

А разве функцию можно передать между потоками?

Это ж как надо расстреливать ноги, чтобы в nodejs нитка, о существовании которой я не подозреваю, дёргала "мои" колбеки?)

Ой да ладно. Проблемы с транзакциями существуют когда в одной транзакции трогается несколько ключей. Если же каждый раз щупается один ключ, то ни тебе дедлоков, ни тебе отката трагзакций. Все очень даже неплохо масштабируется, если правильно готовит.


Да, в редисе есть возможность использовать и что-то, что они называют транзакциями, и Lua процедуры. Но на практике этим пользуются невероятно редко.


Кстати, в KeyDB весь выигрыш только из распараллеливания сетевого взаимодействия. Вся работа с данными идет под глобальным локом.
Т.е.:
а) сетевое взаимодействие настолько накладно, что есть выигрыш от мношопоточности
б) типичная работа с данными настолько быстрая (в redis/keydb), что делать ее под глобальным локом не больно. А значит нет дедлоков и откатов транзакций.
в) конечно, если поставить keydb на 32 ядерную машину, проблемы от глобального лока начнутся. Так что им есть куда расти.

> что они называют транзакциями, и Lua процедуры. Но на практике этим пользуются невероятно редко

Ну как так «невероятно редко». У нас например невероятно часто. Это же зависит от кейса — если кэш, то они не нужны. Если хранение данных, то нужны «часто».
> Если хранение данных, то нужны «часто».

Храните данные в Redis?… у вас стальные яйца, я вам скажу. Зная, как работает Redis, я бы не стал в нём ни чего хранить.

Если вам нужно inMemory, посмотрите хотя бы в сторону Tarantool. Он намного надёжнее в плане сохранности. А так же гибче. И вряд ли медленнее.
сессии юзеров, фоновые задачи, csrf токены, межсервисные локи, различные другие токены, коды подтвеждений sms — всё отлично там хранится.
у редиса два механизма записи на диск — снапшоты и AOF. не вижу повода не хранить там даже важные данные.
> сессии юзеров, фоновые задачи, csrf токены, межсервисные локи, различные другие токены, коды подтвеждений sms — всё отлично там хранится.

Т.е. любые данные, которые вроде и не хотелось бы потерять, но если потеряются, то и хрен с ними. Да, такое можно.

> у редиса два механизма записи на диск — снапшоты и 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 запросы) даже если диск подтупил слегка.
НЛО прилетело и опубликовало эту надпись здесь
Допустим, у нас Lua процедуры интенсивно используются в Redis. Но работают в основном с одним ключом (с одним Hash). В redis-cluster вообще сильно не попользуешься «разными ключами». Можно, конечно, если использовать фигурные скобки а-ля `namespace:{my-shard-key}-subkey`, но напряжно.

А что я должен был понять?
НЛО прилетело и опубликовало эту надпись здесь
А вот статистика по операции get в Redis:


А что подразумевается под «cpm», можно уточнить?
Call Per Minute.
А можно приоткрыть завесу над инвалидацией кеша?
Что именно мешало в ней шардировать редис?
Очень хотелось!
Но как всегда — на проде невозможно, кто же нам даст терзать прод в свою волю. А чтобы это воспроизвести не на проде — нужно поднимать идентичный тестовый стенд, на что конечно же нет ресурсов.
Учитывая, что это php, и вряд ли они делали руками пайплаининг, редис упирался в sys cpu: чтение/запись в сеть.

С хорошим pipelining редис может миллион rps на половинке ядра выдать.

На нормальной железке, redis упирается в одно ядро процессора.

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.