Одна правка документа перегрузила PostgreSQL. Как в Django переделали кеш
Команда Джонни Метца хранила в Redis готовый список документов для каждого пользователя. Когда крупный клиент изменил одну общую запись, обработчик сбросил кеш тысяч пользователей. Их следующие запросы почти одновременно пошли в PostgreSQL, и API несколько минут работал медленнее.
Кеш разделили. Для пользователя хранят только ID доступных ему документов. Каждый документ лежит в Redis в одном экземпляре, а Django забирает нужные записи пачкой через
TTL увеличили до семи дней. Ключи удаляют после коммита через
За три месяца внедрения трафик вырос примерно на 40%, средняя задержка упала примерно на 40%, а число запросов к БД в секунду сократилось вдвое. На обычном пике API обслуживает около 1 100 запросов в секунду, доля попаданий в кеш составляет 97%.
https://johnnymetz.com/posts/caching-at-scale-in-django/
Команда Джонни Метца хранила в Redis готовый список документов для каждого пользователя. Когда крупный клиент изменил одну общую запись, обработчик сбросил кеш тысяч пользователей. Их следующие запросы почти одновременно пошли в PostgreSQL, и API несколько минут работал медленнее.
Кеш разделили. Для пользователя хранят только ID доступных ему документов. Каждый документ лежит в Redis в одном экземпляре, а Django забирает нужные записи пачкой через
get_many. Поле can_edit вычисляют при сборке ответа с учётом прав конкретного пользователя. Теперь при переименовании документа достаточно удалить один ключ doc:<id>.TTL увеличили до семи дней. Ключи удаляют после коммита через
transaction.on_commit: если удалить ключ раньше, параллельный запрос может снова положить в кеш старые данные. При промахе читают из primary, чтобы в кеш не попала устаревшая версия с отстающей реплики.За три месяца внедрения трафик вырос примерно на 40%, средняя задержка упала примерно на 40%, а число запросов к БД в секунду сократилось вдвое. На обычном пике API обслуживает около 1 100 запросов в секунду, доля попаданий в кеш составляет 97%.
https://johnnymetz.com/posts/caching-at-scale-in-django/
Johnny Metz
Caching at Scale in Django: Lessons from Production
What we learned caching a busy Django API in Redis: cache shared data once, pair long TTLs with invalidation you can trust, and fail open when Redis fails.