Точно скажу, что костыли и велосипеды не лучшее решение, особенно если мы говорим о кэшировании, а конкретнее, если нам надо оптимизировать метод доступа к данным, чтобы он имел производительность выше, чем на источнике. Я докажу это на нескольких примерах, приведённых в статье, всего за 5 минут. Прежде чем раскрыть всю суть, отмечу, что эта статья — продолжение нашего цикла про архитектуру highload-систем, где главным героем будет кэширование. Ранее, в материале «Big Data с «кремом» от LinkedIn: инструкция о том, как правильно строить архитектуру системы», я вскользь коснулся вопроса кэширования данных, как способа снижения нагрузки на СУБД, а значит, повышения производительности нашего приложения. Суть кэширования очень простая – не надо каждый запрос приземлять на СУБД. Как же это реализовать? Давайте разберёмся и начнём с определений и классификации. Кэширование – это подход, который, при правильном (!) использовании значительно ускоряет работу и снижает нагрузку на вычислительные ресурсы. Если ещё проще, кэширование — это метод оптимизации хранения и/или доступа к данным, при котором операции с этими данными производятся эффективнее, чем на источнике. Теперь о классификации — в рамках этой статьи я хочу подробнее остановиться на двух подходах: LRU-кэширование и кэширование в Redis. Least Recently Used (Вытеснение давно неиспользуемых) LRU — это алгоритм, при котором в первую очередь вытесняется неиспользованный дольше всех элемент. Кэш, реализованный посредством стратегии LRU, упорядочивает элементы в порядке хронологии их использования. Каждый раз, когда мы обращаемся к записи, алгоритм LRU перемещает её в верхнюю часть кэша. Таким образом, алгоритм может быстро определить запись, которая дольше всех не использовалась, проверив конец списка. В модуле стандартной библиотеки Python functools реализован декоратор @lru_cache, дающий возможность кэшировать результат выполнения функций, используя стратегию LRU. Декоратор @lru_cache под капотом использует словарь. Результат выполнения функции кэшируется под ключом, который соответствует вызову функции и её аргументам. О чём это говорит? Самые догадливые уже сообразили: чтобы декоратор работал, — аргументы должны быть хешируемыми. Вот пример: Нам нужно пробежаться по журналу событий (audit_log), где каждый элемент имеет атрибут user_id — уникальный идентификатор пользователя, подтверждающий определённое действие пользователем в информационной системе. При этом, один и тот же пользователь обычно совершает множественные действия в системе, а значит, событий с одинаковыми  used_id будет больше 1. Но идентификатор пользователя нам ни о чём не говорит. Это просто UUID и если вы не вундеркинд, который запоминает 100 знаков после запятой в числе π, то вам проще оперировать фамилией, именем и отчеством (ФИО). А где лежит ФИО? Правильно — в СУБД, в табличке с пользователями. И что теперь каждый раз делать запрос в СУБД по одному и тому же user_id, чтобы получить ФИО? Конечно, нет! Применим LRU декоратор уже на конкретном примере: Одна строчка кода, которая декорирует функцию get_fio_by_id() и мы уже прикрутили LRU кэш + существенно повысили производительность приложения!  А что, если пойти ещё дальше? Мы же имеем большое распределённое приложение, и многие микросервисы ходят в СУБД за одинаковыми справочными данными. Конечно, можно везде накрутить LRU-кэши, но при этом, нам всё равно придётся из каждого сервиса делать запросы в СУБД за одинаковыми данными. Чтобы этого избежать, давайте использовать централизованный отказоустойчивый кэш на базе Redis! Возможно ли обойтись одной строчкой в коде как в случае с LRU? Да! Самые внимательные и опытные уже наверняка догадались – нам нужен «Декоратор!».
Easy, here we go: Если тут совсем ничего не понятно, то пора повторять матчасть по устройству декораторов в python.  Остался последний шаг — вишенка на торте в нашем декоре. Чтобы всё это гениальное творение использовать в приложении — просто меняем декоратор @lru_cache на @redis_cache.  UPDATE: Как справедливо отметили внимательные читатели, существует множество готовых к использованию библиотек для различных способов и стратегий кеширования: aiocache, cacheout, python-cache, cachetools. Список бесконечный... That’s it! CTO