Состоялся релиз СУБД Valkey 8.1, ответвившейся от СУБД Redis после её перехода на проприетарную лицензию. Проект развивается на нейтральной площадке под покровительством организации Linux Foundation при участии разработчиков из таких компаний, как Amazon, Google, Oracle, Ericsson и Snap. К разработке Valkey присоединился Маделин Олсон (Madelyn Olson), бывший мэйнтейнер Redis. Код проекта написан на языке Си и распространяется под лицензией BSD. Поддерживается работа в Linux, macOS, OpenBSD, NetBSD и FreeBSD...Подробнее: https://www.opennet.dev/opennews/art.shtml?num=63023
Весь этот ваш редис это 200 строк на любом языке. Его любая нейросеть пишет меньше чем за 10 вопросов. Зачем это все?
Ну как же, за 200 строк засмеют, чтоб в продакшен нужно минимум 20000, шоб солидно было, шоб энтерпрайз!
Вот так директор посмотрит шо там эти программисты накодили, увидит эти 200 строк, и возмутиться, за что тут зарплаты то платить?
Нужно чтобы еще память кушало прилично, постоянно молотило cpu и имело крипое API.
Официальный GUI клиент должен быть написан на электроне, иметь крупные UI контролы, и мыльное ШГ.Вот тогда это enter_price.
> Весь этот ваш редис это 200 строк на любом языке.Ну иди и напиши эти 200 строк кода на любом языке.
Все будем пользоваться, донатить и прославлять Анонима.
он хотел сказать что эта шляпа никому не нужна, и ее тащат в кривые проекты для кеширования
> он хотел сказать что эта шляпа никому не нужна, и ее тащат в кривые проекты для кешированияДопустим. Ну расскажи тогда, как правильно сделать распределённый счётчик на чём-то кроме редиса.
Вот тебе пример даже: у тебя в базе есть таблица, описывающая отношение пользователя и количества его рефералов. А теперь представь, что кол разместил в своей группе ссылку. Тебе пошёл траффик на регистрацию. Каждый регистрирующийся должен инкрементить количество рефералов кола в этой таблице. Каждый такой UPDATE лочит строчку, и блокирует все остальные.
Классическое решение -- вынести логику инкремента в редис, и в отдельном процессе периодически сбрасывать количество новоприбывших рефералов в базу. Поскольку база медленная, а редис быстрый, это решение весьма неплохо работает, и позволяет выдержать траффик на пару порядков выше.
Вот. А теперь я готов с интересом выслушать твой рассказ о том, какое это хреновое решение, и как на самом деле надо делать. Ведь "эта шляпа никому не нужна", да?
>кол
>траффик на регистрацию
>рефералИ все это в перемешку с русским языком.
От такого чтива глаза слезятся.Так тяжело написать слово на английском или его перевод на русским языке? Зачем этот суржик?
Слова истинного интернет война. Заветы "Не шаришь в теме - прикопайся к тексту."
Правильно человек выше написал:реферал и другие xералы нам не нужны.
Сначала научись уважать свой язык, свою страну, а потом квакай из своего мультикультурного-болотца, братец Иванушка.
Таблица (только) для insert. Периодически сбрасываешь count(*) в счётчик.
> Таблица (только) для insert. Периодически сбрасываешь count(*) в счётчик.Счётчик в redis имеет сложность O(1), а счётчик на базе count(*) -- O(N), где N -- количество записей в таблице; несравнимо.
>> инкрементить количество рефералов кола в этой таблице. Каждый такой UPDATE лочит строчку, и блокирует все остальные.Это из 90тых годов чтоли? Обновление одного int в базе в миллион раз быстрее внесения записи о новом пользователе.
Там миллиард рефералов в секунду, но все одинаковые.
> миллиардот одного (ну, ладно, двух ... дестяков ) клиента?
или от миллиарда ботов со всего мира?Если от одного клиента, то редис не нужен.
Если от миллиарда ботов, то редис тем более не поможет.
Да, боюсь мы не узнаем, куда надо рефералов приводить. :)
Редис хорошо ложится на модные "микросервисы". Лень делать "монолит" с кешем. Разбиваем на два (или более) микросервиса, и рассказываем сказки, как легко можно масштабировать на миллиард клиентов и на миллиард кешей.
Лень - это когда умеешь, но не хочется. Я вот не умею, потому мне не лень. Но разница инкремента и создания понятна интуитивно. Потому и удивило, на кого такие сказки рассчитаны. Рассказывает ведь очень уверенно. Если кому-то вдруг прокатило, то может и с рефералами не заметят? :)
Ну и в HyperLogLog их. Нафига хранить список-то? Если у вас такие объемы что это уже big data, так нужно брать решения созданные для big data.
Все как ты написал. Инкрементируй счётчик у себя в памяти процесса, периодически обновляй строку в базе и тут же читай её, чтоб видеть, что там надобавляли другие процессы. Редис не нужон.
> Инкрементируй счётчик у себя в памяти процессаТак у тебя инстансов может быть больше одного.
Ты точно знаешь как инкремент работает? Ему и миллион инстансов не помешает.
> счётчик у себя в памяти процессаСервис перестанет быть stateless. Негативные последствия этого решения перечислять можно долго.
>> счётчик у себя в памяти процесса
> Сервис перестанет быть stateless. Негативные последствия этого решения перечислять можно
> долго.а он и так не стейтлес, то что ты вынес его состояние в отдельный процесс сути не меняет
и еще даже если ты обрабатываешь инкрементирование реферала всего 1-го в данный момент времени, то это все равно состояние сервиса
абсолютно неважно ты хранишь данные об одном реферале или нескольких, оно все еще stateful пока не будет флаша и корректной остановки сервера
с тем же успехом ты падаешь на момент передачи в редис, т.е. хрен редьки не слаще
> а он и так не стейтлес, то что ты вынес его состояние в отдельный процесс сути не меняетМеняет. По определению.
> и еще даже если ты обрабатываешь инкрементирование реферала всего 1-го в данный момент времени, то это все равно состояние сервиса
Нет конечно, это не состояние сервиса. В сервисе -- процедура с сайд-эффектом. А стейт -- в редисе.
> с тем же успехом ты падаешь на момент передачи в редис, т.е. хрен редьки не слаще
Импакт разный.
>> а он и так не стейтлес, то что ты вынес его состояние в отдельный процесс сути не меняет
> Меняет. По определению.
>> и еще даже если ты обрабатываешь инкрементирование реферала всего 1-го в данный момент времени, то это все равно состояние сервиса
> Нет конечно, это не состояние сервиса. В сервисе -- процедура с сайд-эффектом.
> А стейт -- в редисе.
>> с тем же успехом ты падаешь на момент передачи в редис, т.е. хрен редьки не слаще
> Импакт разный.ничего не меняет, сначала это состояние хранится на уровне твоего инстанса и только потом ты его мувишь в отдельный сервис, потеря этого состояния на уровне твоего инстанса, а не редиса, будет иметь такой же импакт - некоретное число, и это же очевидно, что потеря одного реферала, что 100 рефералов в общем количестве рефералов делает результат неконсистемным и его все равно надо пересчитывать, импакт тот же
>[оверквотинг удален]
> в своей группе ссылку. Тебе пошёл траффик на регистрацию. Каждый регистрирующийся
> должен инкрементить количество рефералов кола в этой таблице. Каждый такой UPDATE
> лочит строчку, и блокирует все остальные.
> Классическое решение -- вынести логику инкремента в редис, и в отдельном процессе
> периодически сбрасывать количество новоприбывших рефералов в базу. Поскольку база медленная,
> а редис быстрый, это решение весьма неплохо работает, и позволяет выдержать
> траффик на пару порядков выше.
> Вот. А теперь я готов с интересом выслушать твой рассказ о том,
> какое это хреновое решение, и как на самом деле надо делать.
> Ведь "эта шляпа никому не нужна", да?Редис в этом случае будет не распределенным, твоя запись о количестве рефералов будет существовать в единственном экземпляре, более того сам редис однопоточный.
Конечно многопоточный код может тупить на примитивах синхронизации, но все же я ожидаю прирост от многопоточности.
Допустим ты имел ввиду, что к редису будут обращаются из нескольких клиентских приложений (например сервисов или несколько инстансов), тогда вынесение в отдельный процесс имеет смысл, но кто мешает тебе хранить это в собственной памяти. Ты получишь максимальную производительность в памяти без оверхеда Редиса. Если хочешь ты можешь поддерживать стандартный интерфейс например IDistributedCache в .NET. А также в дополнение этот сервис может иметь специфичный API - например AddReferal(...), CountReferals(...) и собственные протоколы в том числе бинарные, что быстрее чем Redis.
И это все актуально, если предположить, что ты реально не можешь обновлять базу данных. А хочешь хостить отдельный процесс для этих целей.
Есть другой вариант, когда тебе неважно точное значение и ты можешь пожертвовать актуальностью значения за последних n секунд. Хранишь кортеж (Count, CountingTime), и обновляешь Count в процессе выборки статы, если CountingTime превышает допустимый.
Но возможно ты не собираешься хранить рефералов вообще, тогда это не сработает, что кстати странно, потому что, кто чей реферал - это необходимая информацию.Допустим у нас не один экземпляр приложения а несколько, поэтому просто кеш на уровне приложения тебе видется проблематичным (и именно поэтому ты почему то назвал его распределенным, хотя в реальности распределенный означает несколько серверов редиса для объединения ресурсов, чего явно не нужно для хранения одной строки). Короче у тебя веб-ферма и балансировка нагрузки для твоего приложения, тогда каждый инстанс может кешировать количество запросов прошедших через него независимо, и обновлять раз в секунду общее значение, просто инкременируя его на SQL параметер через обычный SQL запрос. Даже если у тебя в ферме 10 экземпляров, то будет всего 10 апдейтов в секунду. Ну это все примерно и условно, для наглядности.
Мне например такая формулировка кажется максимально странной:
> Каждый такой UPDATE лочит строчку, и блокирует все остальные.То что что-то там блокируется для обеспечения изоляции транзакции - возможно, надо смотреть какие запросы и какой уровень изоляции, но что значит лочит/блокирует? лочит это и есть блокировка, и лочить он будет только одну строку.
Но давай разбираться насколько плохо для такой задачи СУБД, давай померяем sysbench...
Для теста я взял один из моих серверов, который стоит всего 30 евро в месяц, СУБД 120 GB. В память не помещается само собой... за 30 то евро )))
sysbench oltp_update_non_index, таблица 10 млн строк, обновляем неиндексируемый столбец (количество), обновляем только 1 одну и ту же строку (но это не влияет на результат, можем обновлять разные, но мы моделируем твои условия)
1 поток
queries: 260.14 per sec.
95th percentile: 4.25 ms8 потоков
queries: 1094.86 per sec.
95th percentile: 7.98 ms32 потока
queries: 4236.25 per sec.
95th percentile: 8.58 ms128 потоков
queries: 14029.49 per sec.
95th percentile: 13.70 msКоличество потоков, это количество клиентских потоков, они запускались на том же сервере, отъедая его ресурсы, но не суть, чем больше клиентов, тем больше общая производительность.
Тестировалось на InnoDB, постгрес должен быть еще чуть быстрее, также если дурабилити неважна и это отдельный сервис со своей собственной БД, то можно в MySQL отключить автофлаш на каждую транзакцию, поставить например на 1-2 секунды, скорость увеличится еще, потенциально на порядок.
но даже 10 тыс в секунду рефералов? это мало? на таком начальном сервере?
итак в приоритете в порядке убывания привлекательности:
1) СУБД
2) Кеш в единичном или в каждом инстансе со сбросом в базу
3) Свой микросервис оптимизированный под задачу
4) И только потом некий универсальный тормознутый комбайнИ по-хорошему не надо забывать, что рефералов все равно надо сохранять, а не только их количество и тогда количество стратегий еще возрастает.
Я ответил на твой вопрос?
Ух ты. Я стимулировал кого-то учиться, хоть и таким странным образом. Прям приятно! =)Ну ладно, раз уж пошла такая свистопляска, что ж, объясню пару моментов, которые ты упустил.
---
Первую половину текста ты посвятил размышлению о том, что можно было бы хранить счётчик в памяти каждого инстанса сервиса. Как я уже писал ранее -- это наделяет сервис стейтом, а стейт есть возможность потерять. Если ты делегируешь сервису хранение стейта хотя бы и в виде банального счётчика, то ты должен учитывать весьма много вещей:
Во-первых ты должен предусмотреть процедуру корректного сохранения стейта в базу при завершении сервиса.
Во-вторых ты должен как-то гарантировать, что работа этой процедуры уложится в положенное время, потому что сервис, который завершается слишком долго, в конце концов получает sigkill.
В-третьих сервис может аварийно завершиться из-за непредвиденной ситуации: разработчик ошибся, тестирование не отловило, сервис сдох -- всё, стейт утерян.
Первое ты ещё можешь как-то обеспечить. Второе и третье -- ты не контролируешь вообще.А вот если ты решишь использовать redis, то ты можешь даже не думать обо всём этом: счётчик ведётся в отдельном сервисе, можешь обновляться в любой момент, и это совершенно безопасно.
---
Далее вторая половина текста. Тесты. Очень жаль, но ты допустил ошибку в методике тестирования. Продемонстрированный qps просто нереален, тут уже должен был глаз задёргаться. Плюс к тому, ты сюда скопировал показатели латентности q95, которые в данном тесте совершенно не показательны в силу специфики работы sysbench: он просто не шлёт новый запрос, пока старый не отработал; так что гипотетически, если бы ты составил тест правильно, ты должен был упереться в полочку, после которой дальнейшее повышение количества тредов вообще не меняло бы картину.
По поводу твоей ошибки, я полагаю, что дело в oltp_update_non_index. Этот тест обновляет рандомные строки, он под это заточен. Я не знаю, как ты его адаптировал к сабжевой задаче, но адаптировал ты его точно неправильно, потому что даже на машине с хорошим ssd-диском крайне затруднительно получить больше 10k qps при инкременте в одной и той же строке. Потому что row-level lock: пока один апдейт не завершится, другой не пройдёт.
Далее. Ты не учитываешь тот факт, что база на проде -- никогда не standalone. Она как правило имеет 2 синхронные реплики. А это значит, что значение, полученное в тесте над standalone -- можешь смело делить на 5.
Короче, в бою ты из СУБД сможешь выжать конкретно для операции инкремента одной строки что-то около 2000 qps, и это ещё без учёта того, что на ней будет и иная промышленная нагрузка в том числе.
В то же время от redis ты получишь 100.000 qps без каких бы то ни было ухищрений.
---
> Я ответил на твой вопрос?
Скорее я ответил на твой. =)
я думал ты умнее, но нет, кроме наивновсти и ЧСВ ничего не вижуу меня нет возможности расписывать тебе все еще раз, разжевывая что к чему, но хотя бы пару моментов основных
> - хранить счётчик в памяти каждого инстанса сервиса.
ты смешал понятия сервиса и веб приложения, сервисом у меня названо то, что занимается этим вне приложения, а случай со счетчиком внутри каждого инстанса относилось к самому приложению
и как я тебе уже говорил, твое веб приложение обрабатывающее запросы точно также stateful, иди прочитай что там написано выше
> Во-первых ты должен предусмотреть процедуру корректного сохранения стейта в базу при завершении сервиса.
Точно также как ты должен предусмотреть процедуру сохранения в свой редис, а если он еще и отвалился, то точно также ждать пока он не поднимется и не обработает запрос
> Во-вторых ты должен как-то гарантировать, что работа этой процедуры уложится в положенное время, потому что сервис, который завершается слишком долго, в конце концов получает sigkill.
Чушь несусветная, и не имеет ничего общего с тем раскладом описанном в предыдущем посте, ищи цифры, но даже если бы это было так, то ты имеешь те же проблемы ожидания при обращении по сетке к редису.
> В-третьих сервис может аварийно завершиться из-за непредвиденной ситуации: разработчик ошибся, тестирование не отловило, сервис сдох -- всё, стейт утерян.
точно также когда ты успел сохранить реферала, но не успел сохранить счетчик в редис
> Первое ты ещё можешь как-то обеспечить. Второе и третье -- ты не контролируешь вообще.
это из области слышал звон, да не знаешь где он
> А вот если ты решишь использовать redis, то ты можешь даже не думать обо всём этом: счётчик ведётся в отдельном сервисе, можешь обновляться в любой момент, и это совершенно безопасно.
буггагагаагагаа
> Далее вторая половина текста. Тесты. Очень жаль, но ты допустил ошибку в методике тестирования. Продемонстрированный qps просто нереален, тут уже должен был глаз задёргаться.
ты знаешь после этого бреда я остальное уже не читал ))) для тебя нереален, а для меня реален, ну у каждого свои возможности
ты мыслишь своими ошибочными категориями, и забываешь что лог транзакций может не модифицировать оригинальную страницу, а может сбросить все позже, а до этого у него многопоточная вставка с огромной глубиной очереди, тесты сам надеюсь в инете поищешь
Ну что тут сказать. Бог свидетель, я честно попытался побыть добрым самаритянином.
точно точно, бох свидетель, никакой слепой веры в технических аспектах )))
Вам сюда https://www.youtube.com/watch?v=JeNS1ZNHQs8
Я бы на это посмотрел. Действительно, давай, сделай лучше. Давай сразу на расте, будешь самым модным смузихлёбом на дворе, все корпы будут от тебя зависеть.
кеширование таки действительно делается на си в несколько сотен строк кода, причём кастомное под каждую задачу, видел такое лично в глобальном телеком проекте
Ты про возможности redis знаешь < 0,1%, но все туда-же: "давать советы космического масштаба и космической же глупости" (М.А. Булгаков)Не просто так от безделья разные серьезные люди неоднократно пытаются форкнуть redis. Пока у всех неудачно :-(
KeyDB вполне себе удачный форк. Заменяли им редис на проде крупного проекта
Был, в развитие они не смогли
Эти 99% возможностей редиса никому и не нужны.
>Эти 99% возможностей редиса никому и не нужны.Беда современного образования.
В школе не изучали теорию множеств, потому вместо "мне не нужны" пишут "никому не нужны"
Кинь ссылку на свой вариант редиса из двухсот строк.
Уже давно, с началом 21-го века, денег платуть не за код и софт, а чтоб оно работало у заказчика со всеми его хотелками и перделками, aka поддержка. И вот тут очень быстро окажется, что продухт, который тебе нейросеть выср*т, не работает конкретно у того заказчика конкретно в той ситуации. И тут тебе ни нейросеть не поможет, сколько ты ей вопросов не задавай (ибо данные по специфике заказчика в нейросеть индусы не грузили), ни ты сам, ибо чтоб там тебе нагенерила нейросеть даже разобрать не сможешь.
Ломал голову весь вечер, так и не смог в 200 строк уложиться. Проболва на всех языках какие знию — на Лиспе, Питоне, Расте и Си. Сдаюсь. Показывай как ты сделал.
Надо на perl`е ))
Знал бы Перл — попробовал бы и на Перле. Но я его не знаю.
чо там знать-то, на перле том!
Во, учись:#!env perl
exec '/sbin/redis', @ARGV- и всего две строки получилось!
Интересно как ускоряют детище Сальвадоре
Да никто кроме авторов этим пользоваться не будет. Посмотрят на разборки форков и мигрируют на независимую реализацию, например https://www.opennet.dev/opennews/art.shtml?num=60808
> Проект написан на языке C# с ядром хранения на C++, открыт под лицензией MIT и может работать на всех платформах, поддерживаемых в .NET (Ну нет.
хрен редьки не слаще
> Да никто кроме авторов этим пользоваться не будет.Вы в школу ходили ?
20k>10k
.NET vs native
https://github.com/valkey-io/valkey
vs
https://github.com/microsoft/garnet
Оценивать звёзды в гитхабе, которые легко накручиваются это клиника.
Ага, Майкрософт своим репам на собственном же Гитхабе звёзды накручивает. Наделла по ночам клики скупает за биткоины. Самому не смешно?
> Ага, Майкрософт своим репам на собственном же Гитхабе звёзды накручивает. Наделла по
> ночам клики скупает за биткоины. Самому не смешно?конечно не накручивают но с первой частью полностью согласен, миллионы мух как говорится
> Оценивать звёзды в гитхабе, которые легко накручиваются это клиника.Это кто? Амазон, Гугле и Оракл накручивают ? Против микросовта, сплочились и как на опеннете плюсуют, плюсут... Дали команду всем джунам и те сидят весь день кликают, кликают...
Здесь уже боюсь и клиника не поможет с такой фантазией...
а Вы.. Вы в принципе думаете перед написанием ?
>.net vs nativeчто вообще может быть глупее.
.net давно ил в биткод ллвм'а переводит.
> .net давно ил в биткод ллвм'а переводит.Но подтвердить это ссылкой на доку ты конечно не сможешь?
>> .net давно ил в биткод ллвм'а переводит.
> Но подтвердить это ссылкой на доку ты конечно не сможешь?Это скорее, "слышала звон, да не знает где он" или просто повыёкиваться. Разговор скорее про иследовательский проект LLILC, но это только research, который не изпользуется в стандартном .NET-e или намек нам глупым что мы тупые никогда не слышали про Ahead-Of-Time, где в пайплайне юзается LLVM в тулчайне для создания нативного машинного кода, но при этом все равно на линковке подцепляет минимальную CoreRT, но это не значит что создаются LLVM-овские .bc биткод файлы
> а Вы.. Вы в принципе думаете перед написанием ?Вы только что подтвердили, что да, думаю, в принципе, раз вас зацепило блестнуть своим "превосходством".
> что вообще может быть глупее.
О как?!
Я смотрю Вы быстро подхватываете соответсвующее поведение опенета.
Умничка, не Глупая...
> .net давно ил в биткод ллвм'а переводит.И как это относится к тому, что в гарнете, все еще "как ни странно" ловится "ERR unknown command" ?
Или Вы тоже в тролли подались не одолев
.net (serialization protocol only) vs **native protocol and commands from original fork**.
Попытаюсь для не глупых обяснить - гарнет это RESP совместимый с редиской сервер на протокольном уровне сериализации. Если и это не понятно, то гарнет не замена редиски один в один, или словами микрософта в оригинале: Garnet is not a perfect drop-in replacement for redis.
Прям одни умники, один умный трольнул про гарнет, другой супер умный, умно подхватил на под капотном устройстве...
А тема, да xpен с ней с темой, главное ведь всем показать "умность" что другие - глупые, правда?
- Форк, сделанный Бигтехом никому не нужен?
- Нет, спасибо.
Что значит никому? Разве ещё хоть кто то не перешел? Ну на этот или от M$ ...
ну васяны с подкроватными серверами еще не перешли - они ж до сих пор на центось7, там обновлений не предвидится. Да и им-то "улучшенная" лицензия ничем не повредит, как не были они никому нужны, так и не будут.
лицензия redis как раз антипроприетарная