Comments 28
Хорошая статья, спасибо. Хочу только добавить, что KeyDB не стоит внимания. Данное решение не обновляется уже почти год. Через полтора года после того как перешли под крыло Snap. В процессе эксплуатации пришлось вернуться на Redis в связи с проблемами именно надежности, которые проявились, к сожалению, уже только в проде.
Между командами SCAN и KEYS нет разницы в алгоритмической сложности, если надо пройтись по всем ключам.
Утверждение, что редис используется в основном для кэша, высосано из пальца. Для кэша он как раз не особо полезен.
латенси операции в 100 ns не соответствует действительности. В этом легко убедиться выполнив redis-cli --latency на любом инстансе
Кэш на файловой системе будет быстрее редиса (но не будет распределённым). Намёк на то, что редис быстрее SSD, не соответствует действительности.
группировать команды можно только в том случае, если алгоритм работы с редис это позволяет. Пакетная обработка, разумеется, помогает не только с редисом, но и с любой другой БД. Тут вопрос скорее в эффективности алгоритмов вашего приложения.
А для чего кроме кэша он ещё используется, по вашему?
Нормально работает только как key-database. Да, у него есть другие структуры, но из-за отсутствия транзакций, вы просто устанете реализовывать сложные flow (используя pipiline и compare-and-change подходы, можно, но нужно ли?).
Ещё есть расширение для time-series, но не знаю насколько это востребовано.
Может за последних 3 года ещё что-то появилось? С удовольствием послушаю.
Спасибо за обратную связь. Отвечу по пунктам:
По поводу алгоритмической сложности. Сложность одиночного вызова операции SCAN - O(1). НО Вы совершенно правы, что SCAN для цикла, когда есть несколько вызовов будет иметь сложность O(N), Однако, суть и основной посыл в том, что вы дробите длинную операцию на несколько атомарных вызовов для итерирования по курсору, каждый из которых неблокирующий.
Я не утверждал, что Redis используется исключительно для кэширования. Этот сценарий является одним из самых популярных, наряду с другими.
redis-cli --latency замеряет общую производительность, которая состоит из ряда фаз - сеть и установление TCP-соединения, THP latency, disk io latency если включен AOF, fork latency для RDB снэпшотов и т.д.. Конечно все зависит от вашего окружения - задержки в вашей сети, как затюнен TCP стек и другие параметры OS. Вероятно, вы не будете оспаривать факт того, что redis работает на уровне RAM и средняя скорость обращений на уровне оперативной памяти соответствует значениям, указанным в статье. А визуальная пирамида дана для упрощенного и обобщенного представления о производительности различных компонентов и простоты восприятия этой информации. Я бы подытожил, что redis-cli --latency - это хороший инструмент поиска узких мест для оптимизации и тюнинга производительности Redis.
По поводу SSD: вы не работаете с дисками напрямую в 99.9% случаев, между вами и диском есть абстрактный слой в виде файловой системы, который, как и все в этой жизни, не дается бесплатно и вносит деградацию в части производительности io-операций. DRAM в среднем в 5-10 раз быстрее чем SSD. Конечно, вы можете возразить, что сеть "съедает" все преимущество, но для этого есть pipelining. Замер на единичной операции при которой тот же redis-cli потратит основное время на установку TCP-соединения абсолютно не имеет смысла.
Да, все верно. Разумеется, пакетная обработка (batching) - это универсальный инструмент и работает не только с Redis. И конечно могут быть определенные особенности алгоритмов на уровне приложения, которые могут вас ограничить в части применения этой механики.
Однако, суть и основной посыл в том, что вы дробите длинную операцию на несколько атомарных вызовов для итерирования по курсору, каждый из которых неблокирующий
Дробление улучшает latency, но делает throughput даже хуже.
Основной посыл должен был бы быть, что обе операции вообще лучше избегать
Я не утверждал, что Redis используется исключительно для кэширования. Этот сценарий является одним из самых популярных, наряду с другими.
Мы использовали его для кеширования очень медленных операций - вызов third-party API.
Кеширование редисом данных с высокопроизводительной БД почти наверняка будет бессмысленным. Для таких вещей годятся только локальные кэши
redis-cli --latency замеряет общую производительность, которая состоит из ряда фаз - сеть и установление TCP-соединения, THP latency, disk io latency если включен AOF, fork latency для RDB снэпшотов и т.д..
Ну вот видите, вы просто взяли самую быструю фазу и почему выдали её за конечную латенси, которая на практике никогда не будет достижима.
А визуальная пирамида дана для упрощенного и обобщенного представления о производительности различных компонентов и простоты восприятия этой информации
Эта пирамида только вводит в заблуждение: операции с SSD всегда будут быстрее, если только редис не находится на том же хосте.
Указанные цифры совершенно нереалистичны, как для редиса так и SSD.
PostgreSQL показан невероятно медленным, хотя SQL базы точно так же могут использовать in-memory таблицы.
Конечно, вы можете возразить, что сеть "съедает" все преимущество, но для этого есть pipelining.
Конечно сеть съедает все преимущества. Почему, кстати, в случае с SSD вы "pipelining" тупо проигнорировали? Указанные цифры для диска явно занижены, даже если мы пишем по одному байту.
Замер на единичной операции при которой тот же redis-cli потратит основное время на установку TCP-соединения абсолютно не имеет смысла.
Выше вы писали про кеширование, но в этом случае про какой batching может идти речь? Если же у нас тяжёлая пакетная обработка данных, то зачем нам вообще Redis? Читаем 100M c одного источника, 100M - с другого, как-то обрабатываем в оперативной памяти и выплёвываем в третий. Мне почему-то кажется что Redis - это больше про маленькие и быстрые операции (например rate limiting), чем про большие и жирные.
И, наконец, почему нет сравнения с SQL базам c in-memory движком/таблицами? Хотелось бы хотя бы иметь представление насколько игра стоит свеч, учитывая, что SQL-базы удобнее.
Все верно. Операций сканирования лучше избегать в key-value СУБД. Это антипаттерн. Но иногда это все же требуется и тогда лучше использовать SCAN во избежание блокировок.
При анализе производительности информационных систем наиболее частой проблемой и узким местом является именно база данных и диск. Далеко не все запросы являются высокопроизводительными даже на хорошо оптимизированных структурах и при тщательно подобранных индексах + нет никакого смысла выполнять одинаковые запросы на редко изменяемых данных, создавая паразитную нагрузку на БД. И для этого идеально подходит кэш и нет смысла городить свой доморощенный кэш на уровне приложения. У него масса недостатков. Плюс, очень часто пользователи миксуют OLTP и OLAP запросы, считая, что любая база данных - это нечто универсальное под любой тип нагрузки. Важно помнить, что есть специализированные БД под разные задачи. Например, для OLAP - тот же Clickhouse.
Указанные цифры вполне реалистичны. Обычно мы работаем с Redis с откликом как раз в диапазонах от 100 нс до 10 мкс. Конечно на хорошем оборудовании и оптических сетях.
Не понимаю ваш отсыл к SSD. Диск точно не заменит Redis как инструмент)
Я не писал про сценарий кэширования и батчинг в одном контексте. Это разные кейсы. Батчинг - это просто механика массовой записи и/или чтения. Еще раз напомню, что Redis - это не только кэширование.
Сравнение с другими in-memory СУБД - это предмет отдельной статьи. И не соглашусь, что SQL удобен в 100% случаев. Есть масса кейсов где он не нужен. SQL - это далеко не серебряная пуля и не швейцарский нож.
Однако, суть и основной посыл в том, что вы дробите длинную операцию на несколько атомарных вызовов для итерирования по курсору, каждый из которых неблокирующий.
Я думаю, здесь следует признать, что медленное и проблемное итерирование является очевидным недостатком этой БД. И если в этом возникает необходимость, есть смысл выбрать другую.
При анализе производительности информационных систем наиболее частой проблемой и узким местом является именно база данных и диск
Это далеко не всегда так. Я достаточно много занимался перформанс инжинирингом в предыдущей компании и могу сказать что проблем с производительностью, вызванных злоупотреблением редиса, было намного больше чем от "медленных баз данных" или от кривых индексов. После замены редиса на локальные кэши производительность серьёзно возрастала. Это во-первых.
Во-вторых, с чего вы вообще решили, что при запросе одних и тех же данных базы данных будут дёргать диск? Они и так всё кэшируют в памяти. Не надо считать разработчиков баз данных идиотами.
И для этого идеально подходит кэш.
Кэш может и подходит, но не на основе редиса, он почти всегда слишком медленный для этого.
нет смысла городить свой доморощенный кэш на уровне приложению.
Я нигде не упоминал, что надо писать доморощенный кэш, не понимаю откуда вообще возникла подобная мысль. Вы всегда пишете свой кэш когда надо что-то закэшировать?
Обычно мы работаем с Redis с откликом как раз в диапазонах от 100 нс до 10 мкс.
Раскажите, как вы это делаете. Даже простой пинг будет выполняться дольше чем 100нс.
Запускаем редис на линуксе. Затем на том же инстансе запускаем latency check. На моём лаптопе выдаёт 0.12 ms. Вот вам те же цифры со стек оверфлоу
Я вас уверяю, что доступ к редису из производительной клиентской библиотеки (Jedis) будет иметь примерно такое же латенси.
Не понимаю ваш отсыл к SSD. Диск точно не заменит Redis как инструмент)
Да у вас просто все цифры неверные и запутывают читателя.
Я не писал про сценарий кэширования и батчинг в одном контексте.
Я бы предложил представить хоть сколько-нибудь реалистичные сценарии использования этой БД и от этого отталкиваться.
И не соглашусь, что SQL удобен в 100% случаев.
Для сравнения можно использовать популярные базы. Вы выбрали непопулярные.
Повторюсь, итерирование в key-value БД - это антипаттерн. Если подобная операция вам нужна на большинстве операций, то значит вы неверно выбрали инструмент.
premature optimization - это одна из самых топовых плохих практик в программной инженерии. Обмазать все кэшированием там где надо и не надо в совокупности с непониманием как пользоваться инструментом - это путь к "успеху".
Конечно Вы правы, что в БД существуют инструменты внутреннего кэширования, но они достаточно примитивные и не всегда подходят под конкретные сценарии, а самое главное они неуправляемые, т.к. это для вас черный ящик.
Да, действительно зачастую вполне достаточно использовать простенький LRU кэш на уровне приложения, а полноценный распределенный кэш на базе Redis будет избыточен.
В части того, как мы добиваемся такого низкого latency - ответ простой: У нас очень большие высоконагруженные системы и мы используем высокоскоростные сети и производительное оборудование. Среда запуска проходит тонкий тюнинг в части сетевого стека (selective acks, window scaling, congestion control, tw recycle, syn cookies, размеры буферов и многое другое), threaded io. Возможно, я напишу об этом отдельную статью, рассчитанную на продвинутого читателя.
В статье приведена масса примеров реальных сценариев использования
Не понимаю Вас. Какие непопулярные БД я привел в пример? Объясните мне зачем в Key-Value базе нужен SQL, который несет лишь накладные расходы - парсинг, компиляция, выполнение... Ведь основной паттерн получения данных там по ключу - простой командой GET или MGET в случае групповой операции.
premature optimization - это одна из самых топовых плохих практик в программной инженерии. Обмазать все кэшированием там где надо и не надо в совокупности с непониманием как пользоваться инструментом - это путь к "успеху"
Вы, очевидно, не понимаете разницу между premature optimization и performance enginering-ом. Ну об этом ниже.
Конечно Вы правы, что в БД существуют инструменты внутреннего кэширования, но они достаточно примитивные и не всегда подходят под конкретные сценарии, а самое главное они неуправляемые, т.к. это для вас черный ящик.
У что у нас прям много возможностей повлиять на кеширование в редисе? По-поводу примитивности это ещё надо обосновать.
Да, действительно зачастую вполне достаточно использовать простенький LRU кэш на уровне приложения, а полноценный распределенный кэш на базе Redis будет избыточен.
Кэш может быть простенький, а может быть сложненький. Но если он на основе редиса, то придётся пожертвовать производительностью.
Среда запуска проходит тонкий тюнинг в части сетевого стека (selective acks, window scaling, congestion control, tw recycle, syn cookies, размеры буферов и многое другое), threaded io
Много буков, часть из которых не влияет на вызов к localhost-у, а часть не влияет на латенси. Почему-бы вам не продемонстрировать сие просто скопируя вывод команды reis-cli --latency?
В статье приведена масса примеров реальных сценариев использования
И какай из них подразумевает батчинг и наносекундные задержки?
Объясните мне зачем в Key-Value базе нужен SQL, который несет лишь накладные расходы - парсинг, компиляция, выполнение...
Здесь мы видим типичный пример "premature optimization". Очевидно вы не мерили сколько конкретно длятся "накладные расходы".
А я вот, например, не поленился и померил на совершенно примитивной SQLite c in-memory таблицей
Вставка: 5.719 микросекунд
Итерация: 0.315 микросекунд на запись
Запрос по ключу: 1.301 микросекунд
Как мы видим, на не "высоко-оптимизированом оборудовании" эти ваши "накладные расходы" на 3 порядка ниже, чем сетевые задержки.
Какие непопулярные БД я привел в пример
KeyDB
Хочу подтвердить ваши слова.
Мы из своих сервисов убрали поддержку Redis кэширования.
Т.к. реальные тесты показали, что он (в нашем случае) не дал прироста производительности по сравнению с прямым доступом к настроенному sql серверу.
Все смешалось в кучу в вашем комментарии. Давайте разложим по полочкам:
Я прекрасно понимаю разницу между понятиями premature optimization и performance enginering, но мне совершенно непонятна логика ваших рассуждений. Ниже примеры.
В статье делается обзор in memory СУБД класса key-value. И приводится сравнение именно СУБД этого класса. Более того все эти СУБД имеют одинаковый интерфейс работы с данными и могут взаимозаменяться (drop-in replacement). KeyDB относится к этому классу. Более того - это форк Redis.
В части управления в Redis есть много всего, начиная от TTL и заканчивая алгоритмами вытеснения LRU, LFU. Кэширование же в классических СУБД - это закрытая неуправляемая история.
Повторюсь, redis-cli нельзя рассматривать как инструмент нагрузочного тестирования и мы его не используем для этих целей. А цифры, которые он выдает можно использовать как простейший smoke тест при валидации доступа. Для проведения нагрузочного тестирования есть полноценные инструменты. Нагрузочное тестирование имеет смысл на длинных запусках, когда временем на разовое установление TCP-соединения можно пренебречь, ведь мы же не устанавливаем каждый раз TCP соединение при обращении к БД при чтении или записи ключа.
Если для Вас тюнинг TCP стека - это пустой звук, то вероятно Вы либо не владеете этой предметной областью, либо Вам это просто не требуется в силу специфики Вашей работы и масштаба информационных систем и ПО, которое вы разрабатываете и поддерживаете. Советую, все же изучить хотя бы для развития компетенций и глубокого понимания работы сетевых протоколов.
Redis - это распределенная key-value СУБД, с полноценной отказоустойчивостью, поддержкой шардирования и прочими плюшками, которые нужны для работы огромных гео-распределенных высоконагруженных систем, обрабатывающих сотни терабайт данных. У нас каждый узел в кластере Redis имеет порядка 1 ТБ RAM. А таких узлов много. Данные реплицированы и шардированы.
Вы приводите какие то цифры отклика sqlite в отрыве окружения, от размера dataset и нагрузки на чтение и запись. Это не имеет никакого смысла и не подлежит сравнению.
sqlite - это совершенно иной класс БД и никак не может быть альтернативой Redis по следующим причинам:
Эта встраиваемая СУБД. Работает в рамках процесса самого приложения. В рамках одного инстанса.
Не является распределенной и не имеет адекватного сетевого доступа и интерфейса
Не имеет никаких механизмов отказоустойчивости, включая репликацию
Не является key-value базой и не оптимизирована под key-value доступ
Не являет drop-in replacement в части совместимости с Redis
Используется для небольших объемов данных и в основном там где не нужна полноценная СУБД со всеми вытекающими - нет администрирования, нет зависимостей, нет вычислительных ресурсов...
В определенных кейсах наверное может использоваться в качестве кэша, но чаще всего используется в десктопных легаси приложениях для хранения конфигурации, либо как небольшая встроенная БД для каких то небольших маломощных устройств
По поводу 5-го пункта. Скажите, а Redis вы используете прям как БД?
Другими словами он отвечает за данные как мастер?
Или же мастером за данные в Redis отвечает другая БД, а редис используется для оптимизации доступа туда?
У нас различные сценарии:
Кэш для другой СУБД (избирательный, не все подряд)
Распределенные блокировки
Мастер система, например, как система хранения результатов выполнения асинхронных задач
Брокер для взаимодействия распределенных приложений
Другие сценарии
В статье делается обзор in memory СУБД класса key-value
Ну ОК. Я лично увидел в этом недостаток статьи и некую недосказанность
Я прекрасно понимаю разницу между понятиями premature optimization и performance enginering
Я тогда не понимаю, зачем вы упомянули premature optimization всуе.
Для проведения нагрузочного тестирования есть полноценные инструменты. Нагрузочное тестирование имеет смысл на длинных запусках, когда временем на разовое установление TCP-соединения можно пренебречь, ведь мы же не устанавливаем каждый раз TCP соединение при обращении к БД при чтении или записи ключа
И какой же инструмент даёт наносекундные латенси?? Так же непонятно почему вы решили что redis-cli каждый раз открывает новое соединение. Вы считаете разработчиков редиса некомпетентными?
У меня простой тупой вопрос: какая библиотека и при каких условиях даёт латенси в 100нс при обращении к редис.
Если для Вас тюнинг TCP стека - это пустой звук, то вероятно Вы либо не владеете этой предметной областью, либо Вам это просто не требуется в силу специфики Вашей работы и масштаба информационных систем и ПО, которое вы разрабатываете и поддерживаете. Советую, все же изучить хотя бы для развития компетенций и глубокого понимания работы сетевых протоколов.
Повторю вопрос к экспертам по тюнингу TCP стека: что надо сделать чтобы хотя бы на localhost-е достичь задержки в 100нс
sqlite - это совершенно иной класс БД и никак не может быть альтернативой Redis по следующим причинам:
Я прекрасно знаю что такое SQLite и работал с ней не меньше вашего. Совершенно не обязательно расписывать её особенности.
Я привёл её в качества контрпримера к очевидно абсурдному утверждению, что якобы SQL-движок сам по себе "всё замедляет".
Если вы прочитаете мой самый первый комментарии то увидите замечания, которые вы так и не смогли опровергнуть:
Цифры нарисованные на пирамиде высосаны из пальца и не соответствуют действительности чуть менее чем полностью
ценность этой БД для кэширования весьма ограничена и может быть оправдана в весьма специфичных случаях.
Рассчитывать что редис будет обрабатывать операции скопом - странная идея, ибо редис больше предназначен для быстрых и мелких операций: локи, распределённые счётчики и пр.
Пакетная обработка больших объёмов чаще упирается в оборудование, чем в софт.
Про кэширование редисом еще нужно говорить в разрезе масшатаба системы. Если у вас один инстанс приложения, то Redis тут действительно не нужен. Если же инстансов много, хит-рейт локального кэша может быть крайне низким и в таком случае Redis-кластер, например, вполне нормально подходит.
Спасибо за мнение!
хотелось бы поддержать предыдущего комментатора в вопросе
@akomiaginпожалуйста, покажите, как с помощью перечисленных вами инструментов тюнинга сетевого стека
(selective acks, window scaling, congestion control, tw recycle, syn cookies, размеры буферов и многое другое)
вы получаете наносекундные задержки хотя бы на локалхосте?
Подскажите, на дедикейт сервере с NWMe диском кеширование сейчас настроено в REDIS, который на этом же сервере, если переключить на локальный кеш, будет быстрее, медленнее?
Статья хорошая, хотя начало напомнило википедию, а вот дальше пошло интересней
Хазлкаст годится в аналоги, штука тоже довольно годная.
Ну и, 100мс обращение к SSD бросается в глаза. Ssd сейчас очень быстрые и буфферизованные
Спасибо! Без истории создания наверное было бы не так интересно. Люблю добавить немного беллетристики для легкости чтения и завершенности) Да. HazelCast стоит рассмотреть в перспективе, возможно напишу статью...
По производительности SSD привел средние цифры по больнице чтобы просто дать сравнительное представление. Понятно, что на рынке есть SSD M2 NMWe с DRAM буфером, но есть и другие...
REDIS: такой простой и такой сложный