Я был на собеседовании для среднего / старшего разработчика PHP пару дней назад (у меня не получилось). Мне задали сложный вопрос, который все еще беспокоит меня.
Представьте, что мы используем PHP + Memcached и чрезвычайно загруженный проект (около 100 хитов в секунду и более). У нас есть огромный запрос SQL выполнить, поэтому мы решили кешировать его в Memcached. Теперь срок действия кэша истек, и нам нужно снова выполнить этот огромный запрос для его кэширования, но проблема в том, что все 100 пользователей попадают на сайт одновременно, так что теоретически сервер будет выполнять SQL-запрос 100 раз в одно и то же время для его кеширования, так что сервер отключится, я думаю.
Как мы могли бы решить это? Я думаю, что запрос должен выполнить один раз, и еще 99 парней должны остаться и ждать данных, существующих в Memcached.
У нас есть огромный запрос SQL для выполнения,
Как часто (допустим, ежечасно?). Сколько времени это занимает (допустим, 30м)
Во-первых, никто (клиент, сервер, php, пользователь) не должен запускать событие, которое вызывает запрос. Вам не нужно ничего в интерфейсе, связанного с блокировкой запросов на обслуживание страниц.
Вместо этого вы выполняете запрос в фоновом режиме, в потоке, на другом компьютере, в задании cron (пример: запускайте запрос каждые 1 час, чтобы получить свежие результаты). После завершения запроса вы можете записать в memcache все время, пока система работает.
Таким образом, ни один запрос страницы не вызывает запрос (и, следовательно, блокирует его), кроме того, вы можете стабильно / последовательно обрабатывать 100 запросов, которые были ранее.
Кроме того, вы не будете выполнять 100 копий запроса в MySQL. Было бы выполнить немного параллельно (блокируя остальные), но все остальные 90 ~ запросов будут попадать в кэш SQL-запросов, поэтому он не будет буквально выполнять запрос 100 раз.
Я сомневаюсь, что вы все равно хотите работать в этом месте.
Надеюсь, это имеет смысл!
Мой выбор — добавить дополнительный статус кеша (например, «устаревший»), чтобы пометить записи кеша, у которых истек срок действия и которые находятся в состоянии обновления.
Поэтому, если процесс php запрашивает кэшированные данные у memcached и обнаруживает, что его состояние «просрочено», он устанавливает состояние «устарелое», выбирает свежую версию из базы данных и сохраняет ее как «действительную» в memcached.
Если другой процесс php получит доступ к кэшированным данным со статусом «устаревший», он просто будет использовать устаревшую версию, но не получит свежую версию из базы данных.
Теперь, если вы хотите выжать последний бит производительности, первый процесс php не будет извлекать свежие данные сам, но вместо этого он делегирует эту задачу другому экземпляру (например, с rabbitmq), а также возвращает устаревшие данные.