Уйти в кэш что это значит
Россияне уходят в «кэш». Почему в России массово выводят деньги с банковских счетов
За последние несколько месяцев россияне стремительно снимают денежные средства со счетов в банках. Этот процесс, который начался в середине марта, когда рухнули цены на нефть, а экономику накрыла пандемия, не удалось остановить и сейчас, когда карантинные меры были ослаблены.
Деньги, «бегущие» из банков
Общий объем наличной денежной массы на 1 июня достиг исторического рекорда в 11,2 триллиона рублей. Это почти 80 тысяч рублей на каждого живущего в стране, включая младенцев и стариков. Ничего подобного статистика ЦБ не фиксировала еще ни разу за всю доступную историю.
Почему россияне уходят в кэш
За последние месяцы произошло много событий, которые способствовали массовому бегству из банковской системы. Это, конечно, и обвал цен на нефть, и как следствие этого очередное обесценивание национальной валюты, а так же пандемия коронавируса, которая на длительное время парализовала нормальное функционирование экономики. Многие потеряли работу и были вынуждены снимать деньги со счетов, чтобы прокормить семьи.
Так же уходу в «кэш» способствовало принятие закона о налоге на вклады. После этого сообщения мы наблюдали массовое снятие денег с депозитов. А в июне Центробанк снизил ключевую ставку до 4,5% и пообещал и дальнейшее ее снижение, что прямым образом отразиться на налогооблагаемой базе, а следовательно, и размере самого налога на вклады.
Ну и конечно само снижение ключевой ставки прямым образом влияет на проценты по депозитам, доходность которых с учетом инфляции к концу года скорее всего станет отрицательной. Более подробно я об этом писала здесь Подробнее ➤
Кроме того за последние годы усилились действия властей по ужесточению контроля за счетами и вкладами, что также не способствуют повышению привлекательности безналичных денег. А вскоре, когда будет создан регистр населения России (ЕФИР) контроль за доходами и расходами граждан будет только усилен. Об этом читайте подробнее здесь Подробнее ➤
Таким образом держать деньги на вкладах и счетах в банках становиться не выгодным, а те кто уже вывел свою наличность вряд ли в ближайшее время положат ее обратно на банковские счета.
Черный и серый нал в бизнесе
Судя по данным Центробанка, очень мощное бегство в кэш пошло и со стороны средних и крупных компаний, которые получили огромные кредиты из банковской системы.
Население и бизнес, начали понимать, что экономика захлёбывается, а кризис в стране продлится по всей видимости дольше, чем месяц или полгода. Предположения наших властей о том, что пандемия ускорит закат бумажных денег на фоне развития электронной торговли, оказались мифом. Люди начали панически запасаться наличными банкнотами и предпочитают теперь хранить свои деньги «под матрасом».
И это не удивительно, уж слишком много случаев было в истории нашей страны, когда россияне теряли или все, или значительную часть своих сбережений.
Пересиживать ли кризис в кеше?
Оправдан ли выход из рынка?
В настоящее время множество миллиардеров по всему миру начинают предпочитать самый уязвимый для инфляции, но и один из самых надежных во время кризисов активов — наличные деньги. Проще говоря, речь идет об обналичивании средств, вложенных в мировые рынки. Компания Wealth-X в своем отчете «Перепись миллиардеров мира» изучила движение средств почти 2500 миллиардеров с совокупным капиталом более 7.5 триллиона долларов. Исследования показали, что к настоящему моменту в кеш выведено около 22% средств, что является самым высоким процентом с посткризисного 2010 года. По сравнению с предыдущим годом этот показатель вырос на 5.4% — но много ли выиграли те, кто вывел в предыдущем году?
Напомню, что почти ровно год назад (25 августа 2015) случился «черный понедельник» с кратковременным сильным падением азиатского рынка. В этот день по данным Bank of America Merrill Lynch фонды акций во всем мире лишились около 19 миллиардов долларов, а за неделю с 20 по 26 августа — почти 30 миллиардов. Этот недельный показатель даже превзошел вывод в последний финансовый кризис, т.е. фактически стал самым массовым с начала века.
Однако затем рынок отскочил и уже около года пребывает в боковом движении — а значит, выводившие на просадке недосчитались не менее 10% капитала. Большой вопрос, смогли ли они за год приумножить выведенные деньги на эту сумму.
Тем не менее, причины такой реакции сегодня в общем вполне понятны. Во-первых, это бурный рост американского рынка 2009-2015 годов, которому по преобладающему мнению требуется хотя бы передышка. Во-вторых многих пугает нестабильная ситуация в мире (теракты во Франции, попытка переворота в Турции, Brexit и др.). Наконец, осенью в Америке грядут президентские выборы, причем на этот раз кандидаты стоят на диаметрально противоположенных позициях по многим важным вопросам и по отношению друг к другу доходят до почти прямых оскорблений, что не сулит стабильности.
В таких условиях вполне можно посоревноваться в прогнозах о степени мрачности ближайшего будущего — и даже на время стать гуру, если действительно удастся угадать с кризисом. Российские миллиардеры тоже в тренде: их, правда, больше заботит недвижимость, поскольку рынок аренды в России претерпевает заметный спад. Михаил Прохоров около месяца назад продал сразу 20% акций «Уралкалия» — по некоторым сообщениям, в этом году российский миллиардер хочет обналичить не менее половины своего состояния. Исключения редки — но вот Виктор Вексельберг несколько месяцев назад высказался следующим образом:
Ну и что с этим кэшем делать? Кэш полезен только потому, что, когда возникает опция, у вас есть возможность воспользоваться ею. Оппортунистическая позиция – вы можете купить дешево (в силу сложившейся ситуации). Нет денег – вы этого не купите. Но в конечном счете сидеть в кэше – это не бизнес, это глупо. Вы сегодня какую стоимость денег видите в рынке? В некоторых странах типа Швейцарии она отрицательная, где-то около нуля. Это подталкивает к тому, чтобы поддерживать инвестиционную активность, когда деньги вкладываются.
Аналогичной тенденции перехода в кеш, хотя и в меньшем масштабе, придерживаются крупнейшие мировые хедж-фонды: с начала 2000-х годов доля наличных денег в них достигла максимальной отметки около 6%. Скорее всего, большая часть оставшихся средств вложена в облигации и потрачена на открытие захеджированных коротких позиций по рыночным индексам, товарным активам или отдельным акциям.
Я в этом посте хочу напомнить об отношении к кризису (кажущемуся либо наступившему) с точки зрения портфельного инвестора. Вне зависимости от ситуации, портфельный инвестор находится в рынке, поскольку предсказать точную дату кризиса невозможно; даже перегретый рынок способен приносить прибыль значительно дольше, чем следует из средних значений. А значит, выход из такого рынка это просто потеря упущенной прибыли.
К примеру, американский рынок можно было считать перегревающимся уже в 2013 году — а между тем еще два года по нему шла просто отличная доходность. Кстати, единственный индикатор, за последние 50 лет практически безошибочно предсказывавший кризис (разность в доходности долгосрочных и краткосрочных американских облигаций) в настоящий момент находится на значениях, близких к среднему.
Конечно, нельзя исключить ситуации, когда при наступившем кризисе вам могут срочно понадобиться наличные деньги. Но на этот случай у инвестора просто должен быть сформирован достаточный резервный фонд. Вывод денег на кризисе — одно из самых неудачных решений, которое можно представить; после бурного рыночного роста есть смысл предпочесть защитные активы, среди которых есть по крайней мере две лучшие возможности, чем наличные деньги.
Таким образом, действия портфельного инвестора сводятся не к выводу средств в кеш в подходящий на его взгляд момент, а к стандартной ребалансировке, которая автоматически обеспечит более консервативный портфель при предыдущем рыночном росте. В некоторых стратегиях исходный портфель может предполагать небольшую долю фондов денежного рынка для доливки на просадке — однако это практически тот же выход из рынка.
Уходим в кэш в высоконагруженных системах
Одна из вечных тем — правильная работа с кэшем. Звучит это просто, но на деле в ней очень много подводных камней и особенностей. Ну а когда приходит нагрузка, все становится еще интересней. В кэшировании нет «серебряной пули», а есть набор отработанных техник. И остается лишь подобрать их комбинацию для вашей задачи, используя достоинства и нивелируя недостатки.
На конференции PHP Russia 2021 Павел Паршиков, backend engineer в Авито, представит доклад «Уходим в кэш в высоконагруженных системах». А в этом интервью мы поговорили о том, хорош ли PHP для растущих в плане нагрузки проектов, и какие его инструменты лучше применять.
Расскажи немного о себе. Чем ты занимаешься?
Я работаю инженером в Авито. Уже более 15 лет занимаюсь веб-разработкой, в основном проектированием бэкенда.
Когда я анализирую свое рабочее время, то понимаю, что больше половины занимают коммуникации. Для бэкенд-инженера это общение не только внутри своей команды, но и с ребятами из других групп, из отдаленных частей компании. Для этого нужно уметь задавать только важные вопросы и не тратить ценное время коллег. А в случае удаленной работы на первый план выходит умение правильно и понятно формулировать свои мысли в тексте. Так что хоть мы и программисты, большей частью мы не кодим, а думаем, коммуницируем, проектируем.
Ты занимался наукой и преподавал. Почему ушел из этих областей? Что дал тебе этот опыт?
Работать я начал еще во время обучения в университете. В то время спрос на грамотных разработчиков, даже студентов без опыта, был просто огромным. Поэтому к окончанию университета у меня уже был опыт и желание программировать дальше. Но казалось, что в науке я могу сделать больше, чем просто решить практическую задачу для дипломного проекта. Поэтому поборолся за место в аспирантуре и продолжил обучение. Особенно мотивировала возможность попробовать себя в роли преподавателя. У меня был огромный запал энергии: хотелось рассказать ребятам о том, что знаешь, чему уже научился на практике.
Во время написания диплома я заинтересовался применением различных методик принятия решений в экономике. И в конце концов направление моих исследований сместилось в сторону управления проектами и согласования интересов субподрядчиков-исполнителей работ.
Для поддержки коллективного принятия решений участники таких организаций используют распределенные интеллектуальные системы. Они чем-то похожи на микросервисы, т.к. состоят из независимых модулей, общающихся по стандартизованному протоколу. Такие модули называются программными интеллектуальными агентами, а среда для из взаимодействия — мультиагентной системой.
Они отличаются от классических программных систем в том же, в чем и микросервисная архитектура отличается от монолитной, состоящей из множества подсистем внутри общей системы.
Это интересное и перспективное научное направление. На его развитие я получил грант, исследования финансировал Фонд содействия инновациями. Но потом сил тащить сразу два направления стало не хватать. Для развития необходимо было погружаться глубже либо в науку, либо в разработку программного обеспечения. И я выбрал разработку.
Самое интересное, что я устроился в Авито по рекомендации своего студента. И вообще ребята, у которых я преподавал, успешно работают не только в крупных российских IТ-компаниях (Яндекс, Mail.ru и т.д.), но и в международных технологических гигантах, таких как Google и Apple. И успех учеников, на самом деле, тоже очень сильно мотивирует продолжать обучать, делиться знаниями, помогать ребятам добиваться большего.
Хорош ли PHP для растущих в плане нагрузки проектов?
Начну с того, что как бы ни ругали PHP, некоторые проекты в топе Рунета написаны именно на нём. В качестве языка для бэкенда высоконагруженных приложений, которые я разрабатывал раньше, тоже использовался PHP. И, при этом, они держали нагрузку в тысячи RPS, отлично масштабировались и поддерживались небольшой командой разработки.
На моей нынешней работе используются несколько языков для разработки. Основные — это PHP и Go. На PHP написан весь монолит Авито. Некоторые сервисы также написаны на PHP, например, сервисы для API мобильных приложений (mapi).
PHP точно хорош для растущих в плане рабочих рук проектов. PHP-разработчиков на рынке очень много, и это ребята самого разного уровня. Кроме того, как мы знаем, большинство веб-сайтов написано на PHP, а значит если вы хотите быстро набрать команду, то проще всего будет это сделать для проекта на PHP. Понятно, что большинство сайтов — это совсем не highload, а какие-то малонагруженные полустатические сайты или интернет-магазины, написанные на распространенных, а иногда и самописных CМS’ках. Но научить PHP-разработчика особенностям построения архитектуры под высокую нагрузку гораздо проще, чем заниматься полным переобучением. Ведь это включает в себя не только изучение нового языка, но и его философии, экосистемы, принятых архитектурных паттернов.
Относительно производительности, мы знаем, что PHP с каждой новой версией улучшает использование процессора и памяти. И по benchmark’ам имеет один из самых быстрых интерпретаторов. Дальнейший рост производительности обеспечивается полноценной поддержкой JIT компиляции. Однако PHP уже и так находится на пределе улучшений, если смотреть на производительность вычислений для интерпретируемых языков. По факту, практически все PHP-приложения заняты большую часть времени не вычислениями, а вводом-выводом: походами в сеть в другие сервисы, получением данных из кэша или базы данных и т.д. Т.е. по сути PHP приложение выступает всего лишь клеем, который связывает между собой воедино различные части архитектуры. И в такой типичной задаче для веб-приложения производительность самого языка не так важна. Гораздо важнее производительность архитектуры в целом.
Если ваше приложение уже доросло до выделения некоторой функциональности в отдельные сервисы, стоит отметить один нюанс, существенно ограничивающий использование коробочного PHP в микросервисах. Это отсутствие асинхронности. Для обработки типичного запроса в микросервисной архитектуре нужно сходить в несколько сервисов. Например, на странице поиска это могут быть запросы в сервисы поиска, избранного, картинок, телефонов и т.д. И это слишком непозволительная роскошь — ходить во все сервисы последовательно. Особенно это опасно, когда все N сервисов начинают по чуть-чуть деградировать и тормозить. Тогда все эти задержки накапливаются и увеличивают среднюю деградацию в N раз.
И чем больше сервисов, тем, как правило, запросы в них легче поддаются распараллеливанию. Удобных конструкций для создания параллельных запросов и реализации асинхронности из коробки в PHP нет. Поэтому приходится использовать дополнительные библиотеки и фреймворки, которые реализуют в PHP различные концепции асинхронного программирования: event loop, promises, coroutines. Например, ReactPHP, AMPHP, Swoole.
Для задачи реализации асинхронных походов в несколько микросервисов по HTTP можно взять кое-что попроще. В PHP уже встроена функция curl_multi_exec(), которая умеет выполнять несколько запросов по HTTP параллельно. Я также использую библиотеку Guzzle, которая является удобной оберткой над этой функцией.
В экосистеме PHP большое разнообразие фреймворков. И можно выбрать любой, по душе и по строгости к качеству кода. Зачастую highload-проекты используют свои собственные фреймворки, т.к. стандартные решения часто слишком универсальные и достаточно тяжелые. При этом некоторые модули стандартных фреймворков очень удобны и распространены в сообществе, поэтому часто используются отдельно от него. Например, прекрасный компонент DependencyInjection от Symfony.
Быстродействие особенно важно для микросервисов, которые должны быстро взаимодействовать через API. И слишком дорого на каждый запрос поднимать все окружение фреймворка, парсить конфигурации, загружать множество файлов и создавать экземпляры классов. Проблему можно решить, если сократить объем этого окружения, перейти к микрофреймворку и оптимизировать загружаемые библиотеки. Кроме того, в PHP7.4 появился preloading для однократной предзагрузки скриптов. А еще можно воспользоваться инструментом RoadRunner, который позволяет сохранять состояние скрипта после выполнения запроса.
Если говорить о самом языке, то PHP позволяет удобно описывать бизнес-логику и строить хорошие бизнес-модели. Ведь это полноценный ООП язык со всеми необходимыми штуками, вроде наследования, полиморфизма и т.д. И это гораздо удобнее, чем, например, прототипное наследование в Javascript. Поэтому PHP отлично ложится на такие контексты как, например, автоматизация различных процессов в бэкофисе. PHP позволяет очень быстро прототипировать, и, что важно для бизнеса, снижает time to market в погоне за конкурентами.
Есть ли знания, которые приобретаются только в работе с нагруженными системами? О чем стоит думать? Что можно докрутить потом, а что — делать сразу?
В первую очередь подчеркнул бы, что для highload-проектов выбранная архитектура важнее, чем код и применяемые технологические решения. Не зря на собеседованиях в другие крупные компании обычно одна из секций — архитектурная. Для того, чтобы новая технология попала в техрадар, она должна пройти защиту, учесть рекомендации и получить одобрение. Кэши, про которые я собираюсь рассказать на PHP Russia, — супер важная часть архитектуры высоконагруженного сервиса. Правильно приготовленные, они могут существенно повысить запас прочности системы.
Вы должны заранее продумывать архитектуру и варианты масштабирования системы таким образом, чтобы рост нагрузки не потребовал полного переписывания проекта. Речь идет не только о масштабировании архитектуры системы, но и архитектуре кодовой базы. Во всех случаях ключевым принципом, которого стоит придерживаться, начиная с этапа построения архитектуры и заканчивая непосредственно разработкой, является принцип слабого зацепления (loose coupling). Такую систему в будущем становится гораздо проще «расцепить» на отдельные независимые части.
В монолитном приложении с единой кодовой базой, даже придерживаясь принципов SOLID, сложно поддерживать независимость модулей. Самый надежный вариант снизить зацепление — с самого начала применять внедрение зависимостей (DI). Это позволяет легко отцепить зависимости от клиента и, при необходимости, вынести их в отдельный модуль, библиотеку или даже сервис. В этом случае вы упрощаете для себя модульное тестирование, так как четко определены границы модулей и явно формализованы их контракты. Проще всего сразу использовать контейнер внедрения зависимостей (DIC), который упрощает конфигурирование и инстанцирование зависимостей.
В этом плане микросервисный подход имеет явные преимущества, ведь он воплощает принципы loose coupling в архитектуре, так сказать, by design. Уже на стадии проектирования микросервиса мы четко очерчиваем границы его ответственности и описываем его API. Фактически, микросервисы только и связаны через этот API. Написание юнит- и функциональных тестов, мокирование зависимостей доставляют абсолютное удовольствие.
На самом деле, сам PHP тоже оказывает помощь в масштабировании приложений, так как он — stateless по умолчанию. Хотя его модель — «умереть» после обработки запроса — явно проигрывает другим языкам по накладным расходам, проблема с масштабированием веб-сервера на PHP отсутствует. У вас нет никаких общих состояний между запросами, а чаще всего нет и данных в общей памяти. Запросы не просто слабо связаны, они вообще изолированы друг от друга. А значит неважно на каком сервере запросы обрабатываются, один это сервер или множество.
Важно отметить, что при этом не стоит сразу усложнять архитектуру системы и добавлять в нее компоненты, которые не устраняют проблемы, а только усложняют разработку и поддержку. Например, если у вас небольшая команда, объем кодовой базы незначительный, бизнес-логика проста и в ней сложно выделить отдельные области, нет смысла использовать микросервисную архитектуру, даже если нагрузки высокие. Монолитное приложение в таком случае будет гораздо удобней в разработке и поддержке, обеспечит более низкий time to market.
Как говорят, если вы думаете, нужно ли вам шардирование, скорее всего оно вам не нужно. И если вам реально потребуются архитектура и решения для highload, вы будете об этом знать наверняка. В развитии системы нужно двигаться аналогично развитию в продукте, начать с MVP-решения, а потом его итеративно улучшать, гибко планируя доработки. И любой элемент в архитектуре highload-приложения — это всегда способ решить какую-то проблему: улучшить процессы разработки, расширить bottleneck, снять нагрузку с части системы.
Все приложения под highload, как правило, очень специфичны и имеют особенную архитектуру. Эта архитектура определяется профилем нагрузки, поведением пользователей, предметной областью и еще много чем. Сейчас в отрасли сформировались наиболее популярные подходы к контейнеризации приложений, хранению данных, кэшированию. Но эти отдельные технологии и методики можно комбинировать разными способами и получать системы с различными свойствами. Архитектура приложения — это результат множества компромиссов между стоимостью, масштабируемостью, производительностью и гибкостью. И как раз на компромиссах при выборе решения по кэшированию данных я собираюсь сделать акцент в своем докладе.
В системах, работающих под высокой нагрузкой, начинают проявляться и играть важную роль такие нюансы, которые в обычных условиях просто незаметны. Поэтому от программиста требуется не только писать качественный код, но и понимать, как он работает «под капотом», какие оптимизации могут применяться интерпретатором. А значит надо понимать принципы работы интерпретатора PHP, детали работы с памятью, особенности реализации различных структур данных. Например, как переменные представляются в виде структуры zval, какие подчиненные структуры выделяются для различных типов данных и как «под капотом» работает присваивание по значению и по ссылке. Эти знания обязательно пригодятся, когда вы начнете искать узкие места в коде приложения с помощью профайлера. Иногда приходится погружаться очень глубоко и изучать опкоды, которые сгенерировал интерпретатор.
Для ненагруженных приложений зачастую слишком дорого тратить время разработчика на то, чтобы оптимизировать код. Затраченное время никогда не окупится. Гораздо проще взять сервер помощнее или горизонтально масштабировать систему. В случае высокой нагрузки незначительная оптимизация в ядре фреймворка, через который проходят сотни тысяч запросов в минуту, может уменьшить время выполнения каждого на несколько миллисекунд или сократить потребление памяти. И в итоге это приведет к высвобождению нескольких серверов, каждый из которых стоит несколько тысяч долларов. Оптимизация системы в данном случае имеет конкретную стоимость, и для бизнеса она ниже, чем покупка нового железа.
Рост нагрузки, как правило, приводит к росту архитектуры системы. И в этот момент важно не потерять понимание того, что с системой вообще происходит. И если происходит что-то нехорошее, то почему. Поэтому заранее нужно продумать системный подход к observability системы и детали реализации каждого из его трех столпов: логирование, метрики, трейсинг. В случае микросервисной архитектуры без настроенных «радаров» и продуманной системы алертинга жить невозможно. Ведь если в сложной взаимозависимой системе сервисов начнутся проблемы у одного из них, это автоматически приведет к каскадным проблемам у всех зависимых сервисов.
В итоге даже проблемы в одном сервисе в течении нескольких минут могут привести к убыткам, которые измеряются миллионами рублей.
Сейчас в крупных компаниях даже выделяют отдельно роль инженера по SRE, отвечающего за надежную работу системы. Эту позицию может занять опытный разработчик из команды. Часто эту роль выполняют инженеры-программисты параллельно с основной работой.
О чём собираешься рассказать на PHP Russia?
Кэширование — это такая штука, про которую, вроде бы, все и так знают. Что тут вообще можно изобрести? В PSR’овских рекомендациях интерфейс для Simple Cache насчитывает всего несколько стандартных функций, таких как get, set, delete и т.д.
Но на самом деле если копнуть глубже, выясняется, что кэш — это сложнейшая распределенная система, и даже не все ее части доступны для управления. А те кэши, которыми мы можем управлять, разбросаны по всей сети. Фактически, веб-разработчик любого профиля что-то кэширует: в браузере, на прокси, на серверах и т.д. Конечно, большинство рычагов для управления этой махиной находятся на сервере и в руках бэкенд-разработчиков. Но даже если сосредоточиться на серверном кэшировании, все его виды и техники даже при обзорном рассмотрении никак не поместятся в один доклад. Поэтому я выбрал небольшой кусочек этой огромной кэш-истории, которая ближе всего PHP-разработчикам — кэширование данных в оперативной памяти.
Кэширование в вебе очень многолико. На сервере под кэшированием обычно подразумевают размещение данных в оперативной памяти. Но туда невозможно положить всё, что хотелось бы. Потому готовые к использованию данные можно разместить и в других местах, и даже в одном хранилище, вместе с исходными данными. И это тоже в некоторой степени — кэш. Да, скорость доступа невелика, однако данные уже предвычислены. Так, например, распространено кэширование обработанных картинок (превью) прямо на диске, или размещение аналитических данных вместе с исходными в одной БД, в кэширующих таблицах.
Весь мой доклад будет пронизан мыслью о том, что существует множество техник и приемов для решения каждой из проблем. И их так много только потому, что для каждого кейса необходимо индивидуально подбирать технику, взвешивая ее достоинства и недостатки. Достоинства одной техники могут отлично сработать в одном кейсе, и при этом быть незаметны за ее недостатками в другом. Кэширование работает не всегда. Highload-системы тем и интересны, что стандартных кейсов не бывает, и каждый случай нужно рассматривать отдельно: работает кэширование или нет, какую выбрать политику вытеснения, как поддерживать консистентность и т.д. И тут, как говорил Шерлок Холмс, в вашем арсенале должно быть как можно больше полезных инструментов, которые в идеальном порядке и всегда под рукой.
В докладе я сознательно не акцентирую внимание на каких-то конкретных реализациях распределенных систем для кэширования в памяти, вроде Redis или Memcached. Хотя они, конечно, наиболее распространены и имеют наибольшие комьюнити. Я работал с системами, которые держали тысячи RPS запросов к бекенду, при этом использовали библиотеку Memcache для PHP, у которой из операций с данными есть только get/set/delete/increment/add. И эти операции покрывали 99% всех потребностей по управлению данными в оперативной разделяемой памяти. А более сложные операции с данными можно выполнить через комбинацию простых. Однако здесь возникают различные проблемы атомарности. О том, как с ним работать, я тоже собираюсь рассказать в своем докладе.
Одна из частей доклада будет посвящена вопросу масштабируемости кэширующих систем. Вне зависимости от нагрузки на систему, с масштабированием вы столкнетесь в том случае, если ваши данные просто перестанут помещаться в память одного сервера. Задача распределения данных по кэш-серверам чем-то напоминает шардирование базы данных. Однако между ключами отсутствуют явные связи, поэтому выбираются самые простые функции шардирования, которые часто уже реализованы в клиентских библиотеках. Но вы увидите — все настолько просто, что управлять распределением данных по алгоритму консистентного хэширования можно прямо из своего PHP-кода!
Для highload-систем разделение данных по узлам полезно еще и для масштабирования нагрузки. Из коробки размазывание нагрузки по серверам будет отлично работать для большинства ключей. Но особенное внимание нужно обратить на горячие ключи. Иногда они настолько горячие, что нагрузку на них не вытягивает один кэш-сервер. В докладе я покажу несколько приемов, которые мы используем для того, чтобы горячий ключ не стал глобальным мьютексом для всей системы, сериализующим запросы.
На уровне PHP кода необходимо предусмотреть размазывание нагрузки не только по узлам, но и во времени. На конференции разберем несколько типичных подходов к прогреву кэша и поддержанию его в горячем состоянии.
Правду говорят, что инвалидация кэша — одна из сложнейших проблем программирования?
Скорее, инвалидация — это одна из самых интересных проблем программирования. Кэширование просто напичкано такими интересно-сложными архитектурными проблемами.
Многие разработчики, сталкиваясь с высокими нагрузками и ростом response time, обращаются к кэшированию, как панацее от всех проблем. И действительно, это же так удобно и просто — сохранить копию данных в оперативную память и, за счет этого, снизить время чтения и убрать нагрузку с основного персистентного хранилища. Например, просто кладем в кэш уже заранее сгенерированную ленту для главной страницы сайта или блок с рекомендациями. Теперь время их чтения определяется скоростью оперативной памяти, что просто прекрасно.
Но вдруг в службу поддержки от пользователей начинают поступать жалобы: поменял пост — ничего не изменилось в ленте, нажал лайк — счетчик не обновился в блоке, оплатил выделение объявления цветом — оно отображается как обычное. И тут мы начинаем понимать, что не все так просто. Что делать со значением в кэше, если исходные данные изменились? А ведь наверняка от одного элемента исходных данных зависит множество производных значений в кэше: ленты, блоки, счетчики. Как реализовать консистентность каждой закэшированной копии данных и при этом не получить оверхед, превышающий все преимущества кэширования?
Возможно, эта проблема была названа сложной, потому что она пронизывает все уровни архитектуры вычислительных систем — начиная с аппаратного обеспечения (кэш процессора) и заканчивая прикладным программным обеспечением (кэш браузера). Проблема стоит особенно остро в распределенных веб-системах, где кэши расположены во всей цепочке: у клиента, в сети и на сервере. На сервере нам нужно понимать всю сеть зависимостей между данными в кэшах и исходных хранилищах. Когда мы начинаем размещать данные за пределами сервера, управлять ими становится в разы сложнее. Здесь вступают в игру политики управления кэширования через заголовки и коды состояний HTTP. В итоге получаем сложнейшую распределенную архитектуру, в которой решение задачи согласованности кэшей зачастую нетривиально, а в процессе инвалидации легко упустить какой-нибудь краевой кейс.
Часто можно пожертвовать строгой консистентностью данных. Ведь процесс инвалидации имеет свою стоимость, с точки зрения производительности и использования ресурсов. Многие наши приложения — это совсем не банковские системы, а потому если закэшированный блок будет не консистентен с лентой постов, которая находится рядом с ним, этого могут не заметить.
Но существуют кейсы, не допускающие даже временной неконсистентности данных. И в моем докладе я разберу, какую логику стоит разместить в PHP-коде, чтобы своевременно провести инвалидацию всей копий в кэшах. В простейших случаях, когда между элементами отсутствуют зависимости, можно выбрать стратегию явной инвалидации по конкретному ключу. Если же зависимости присутствуют, нужно отразить их в кэше, чтобы затем сразу выполнять инвалидацию группы элементов. Существуют даже приемы, позволяющие автоматически производить это в кэше, хитро построив ключ!
В задаче инвалидации кэша огромное поле для творчества. И когда строгая консистентность приводит к проблемам производительности или излишнему усложнению архитектуры, можно просто «замаскировать» проблему для пользователя прямо на фронтэнде. Например, по нажатию лайка для поста имитировать на фронтэнде изменение счетчика с рейтингом, маскируя неконсистентность значений в кэше.
Уверен, что после моего доклада слушатели, столкнувшись со сложной проблемой инвалидации, будут иметь «за пазухой» все необходимые инструменты для ее простого решения.
PHP Russia 2021 пройдет 28 июня в Москва, Radisson Slavyanskaya. Но уже сегодня можно ознакомиться с расписанием и присмотреть доклады, которые вы точно не захотите пропустить.
А еще вы можете выбрать формат участия: онлайн или офлайн. Не забудьте купить билеты уже сегодня!