Если честно, я скептически отношусь к keydb, возможно из-за того что не встречал серьезных проблем с redis и его всегда хватало. Насчет поддержки других хранилишь: думал про memcached конечноже, но решил подождать пока кому-нибудь понадобится так как он стремительно теряет свою популярность. А других претендентов пока не вижу.
Хотелось бы большей деталей: к чему эта гонка может привести? Но могу сказать, что в работе с кешом обычно вопрос гонки важен в случае высокой нагрузки на кеш, которая может привести к cache stampede: когда есть кеш в высоким рейтом вызова и вдруг происходит инвалидация, которая приводит к паралеьному пересчету данных для кэша. Можно про него еще вот тут еще почитать.
Для зашиты от этой проблемы есть в библиотеке несколько решений:
1)cache.early декоратор, который кроме обычного ttl имеет второй ttl - ранней экпирации, после которого кэш обновится в бекграунде, причем перерасчет будет гарантировано сделан 1 раз, достигается засчет атомарности операции incr если мы храним кеш в redis. Можно сказать, что это аналог XFetch алгоритма.
2) cache.hit декоратор, который с указанием update_after будет действоватьтакже как cache.early, отлько ориентиром для раннего обновления кеша будет количество хитов.
3) cache.locked декоратор, который поставит лок на исполнении декорируемой функции - таким образом при совмещении 2 декораторов можно будет гарантировать что паралельного перерасчета кеша не будут
Что насчёт возможности декорирования методов класса?
Если вы насчет моей библиотки то их возможно декорировать. Есть маленькая проблема: библиотека дает возможность не указывать ключ для кеша и тогда он будет сгенерирован самой библиотекой
class MyClass:
@cache(ttl="10s")
async def method(self, arg):
...
в таком случае ключ сформируется не совсем валидный: main:method:self:<main.myclass object at 0x10545eeb0>:arg:test
Согласен, что такое поведение не комельфо, но когда разработчик декорирует метод, то не ясно, хочет ли он кеш для класса или для обьекта этого класса. Поэтому правильней будет если разработчик будет указывать конкретный шаблон для ключа:
Про args/kwargs и производительность всего этого каверзных вопросов не задаю) Я сам очень скрипел зубами, если что-то лишнее приходилось делать в рантайме, ибо удобство шло в конфликт с производительностью
Да я понимаю о чем вы, о необходимости получать сигнатуру через интроспекцию? - это дорого, но есть же кэш )
Ну я бы понимал ваше негодование если бы статья называлась "Почему вам стоит использовать async", но у меня статья про другое. Я лиш хотел обозначить свою мотивацию выбора.
Сам писал такие обертки и работал с чужими, сам делал баги и покрывал эти обертки тестами - в результат куча кода, который надо поддерживать. Зачем если можно использовать готовое? Именно в результате осознания этого решил вынести это в библиотеку, о которой в последней части статьи идет речь.
А вот как раз реализации, описанные в статье имею меньший потенциал, так как для части людей они будут избыточны, а для другой не достаточно гибки и производительны.
А можете пояснить почему они будут избыточны? А для других недостаточно производительны?
Если честно, я скептически отношусь к keydb, возможно из-за того что не встречал серьезных проблем с redis и его всегда хватало.
Насчет поддержки других хранилишь: думал про
memcachedконечноже, но решил подождать пока кому-нибудь понадобится так как он стремительно теряет свою популярность. А других претендентов пока не вижу.Хотелось бы большей деталей: к чему эта гонка может привести?
Но могу сказать, что в работе с кешом обычно вопрос гонки важен в случае высокой нагрузки на кеш, которая может привести к cache stampede: когда есть кеш в высоким рейтом вызова и вдруг происходит инвалидация, которая приводит к паралеьному пересчету данных для кэша. Можно про него еще вот тут еще почитать.
Для зашиты от этой проблемы есть в библиотеке несколько решений:
1)
cache.earlyдекоратор, который кроме обычного ttl имеет второй ttl - ранней экпирации, после которого кэш обновится в бекграунде, причем перерасчет будет гарантировано сделан 1 раз, достигается засчет атомарности операции incr если мы храним кеш в redis. Можно сказать, что это аналог XFetch алгоритма.2)
cache.hitдекоратор, который с указаниемupdate_afterбудет действоватьтакже какcache.early,отлько ориентиром для раннего обновления кеша будет количество хитов.3)
cache.lockedдекоратор, который поставит лок на исполнении декорируемой функции - таким образом при совмещении 2 декораторов можно будет гарантировать что паралельного перерасчета кеша не будутЕсли вы насчет моей библиотки то их возможно декорировать. Есть маленькая проблема: библиотека дает возможность не указывать ключ для кеша и тогда он будет сгенерирован самой библиотекой
в таком случае ключ сформируется не совсем валидный:
main:method:self:<main.myclass object at 0x10545eeb0>:arg:testСогласен, что такое поведение не комельфо, но когда разработчик декорирует метод, то не ясно, хочет ли он кеш для класса или для обьекта этого класса. Поэтому правильней будет если разработчик будет указывать конкретный шаблон для ключа:
Да я понимаю о чем вы, о необходимости получать сигнатуру через интроспекцию? - это дорого, но есть же кэш )
Ну я бы понимал ваше негодование если бы статья называлась "Почему вам стоит использовать async", но у меня статья про другое. Я лиш хотел обозначить свою мотивацию выбора.
Сам писал такие обертки и работал с чужими, сам делал баги и покрывал эти обертки тестами - в результат куча кода, который надо поддерживать. Зачем если можно использовать готовое? Именно в результате осознания этого решил вынести это в библиотеку, о которой в последней части статьи идет речь.
Простите, не хотел никого обидеть, когда писал свое видение такой дикой популярности использования async/await в приложениях.
А можете пояснить почему они будут избыточны? А для других недостаточно производительны?