Dog-pile эффект. Как отгонять стаи собак.

апреля 18, 2008 by ptchink

Dog-pile эффект — ситуация когда кэш протухает, а большое количество запросов генерирует высокую нагрузку на источник данных, из которых строиться кэш.

Представьте, что вы кэшируете результат какого то тяжёлого запроса, например, список популярных статей. В какой-то момент времени кэш протухает, и его кто-то должен построить заново. В общем то пока все хорошо. Кроме случаев когда построение кэша тяжёлая операция, а запросов на него много. Например, запрос для генерации кэша занимает 1 секунду, а пользователи ломятся по 10 штуков в секунду. Соответственно, 9 пользователей (кроме первого) будут только зря нагружать базу. А при большом количестве запросов могут и полностью ее положить.

И пусть весь мир подождёт

Первое, что нужно решить — может ли пользователь ждать генерации кэша. Пример с популярными статьями это цветочки, ибо есть еще сложно рассчитываемые рейтинги, которые могут считаться оооочень долго.

Предположим, что у нас простой случай и пользователь не сломается, если подождёт секунду-другую.

Честные блокировки

Решение в лоб. Первый пришедший лочит кэш на запись и отправляется генерировать кэш. Остальные, увидев лок, понимают, что не успели, чешут репы и думают, что делать.

Как именно делать лок зависит только от вашей фантазии и имеющихся средств. Это может быть, что угодно:

Лок файловой системы
много косяков, но иногда работает :). Подробности в описании функции flock() .
Мьютекс в хранилище
Если мы используем memcache и генерируемый кэш имеет ключ «popular_articles», тогда наличие данных с ключем «popular_articles_lock», говорит о том, что наш кэш уже кто-то генерирует. Тоже самое спарведливо и для других хранилищ.
IPC семафоры
Настоящие пацанские семафоры ;) Ни разу не использовал — руки не доходят.

Плюсы локов в том, что клиент сам решает, что делать в ситуации, когда ему нужны данные, а их кто-то генерирует. Например, если есть старые данные, то мы можем их отдать, а если данных нет, то либо подождать, либо честно вывести пользователю, что данных нет. На самом деле висящие в течении секунды пользователи совсем не есть гуд, но иногда можно допустить и такое.

Так же не стоит забывать, что при генерации может возникнуть ошибка, и в этом случае лок может остаться висеть.

Организация «окна» для генерации

Способ был подсмотрен в исходниках какого-то фреймворка :)

Суть его в продлении ttl для генерируемого кэша. Т.е. приходит первый — продлевает ttl существующего кэша на какую-то заранее определённую величину, и начинает генерировать новое значение. Если писатель умирает, то кэш быстро снова протухнет и кто-нибудь подхватит знамя генерации с трупа павшего товарища. Если же все нормально, то будет записан новое значение кэша и установлен новый ttl.

Основной минус такого подхода — способ определения читателями момента, когда старых данных вообще не было, а новые кто-то уже генерирует. Если в подходе с локами этим признаком было отсутствие данных и наличие лока, то в данном подходе нужно что-то предопределённое запихивать в сам кэш.

Я хочу вас всех, я хочу вас сразу!

Случай у нас тяжёлый, и пользователю будет скучно коротать 20 секунд рисуя матом надписи на пыльном столе. Я знаю про кого будут эти надписи.

Главное откровение: чтобы избавиться от последствий многопоточности надо свести ее к одному потоку. Просто и со вкусом. Убираем всю генерацию кэша в оффлайн. ttl-ем в данном случае будет время перезапуска генерирующих кэш скриптов. Помимо быстрого ответа пользователю тут есть еще один плюс — наборы кэшей часто генерировать быстрее, чем каждый из них по отдельности, ибо можно хранить какие-то промежуточные данные.

Иcтoчник: Dog-pile эффект. Как отгонять стаи собак.

Posted in Новости |

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.