2015-02-14 2 views
1

Я был на интервью для среднего/старшего PHP-разработчика пару дней назад (я не смог). Мне задали сложный вопрос, который все еще беспокоил меня.Одновременный звонок в Memcache

Представьте, что мы используем PHP + Memcached и чрезвычайно загруженный проект (около 100 ударов в секунду и более). У нас есть огромный SQL-запрос для выполнения, поэтому мы решили кэшировать его в Memcached. Теперь кеш истек, и нам нужно выполнить этот огромный запрос еще раз, чтобы кэшировать его, но проблема в том, что все 100 пользователей получают на сайте одновременно, поэтому теоретически сервер будет делать SQL-запрос 100 раз в то же время кеш его после, так что сервер будет идти вниз, я думаю.

Как мы можем решить это? Я думаю, что запрос должен выполняться один раз, а еще 99 парней должны оставаться и ждать данных, существующих в Memcached.

ответ

1

У нас есть огромный запрос SQL для выполнения,

Как часто (предположим, ежечасно?). Сколько времени занимает (позволяет предположить 30 м)

Во-первых, никто (клиент, сервер, php, пользователь) не должен увольнять событие, которое делает запрос. Вы не хотите, чтобы что-то на лицевой стороне было связано с блокировкой запросов на страницы.

Вместо этого вы выполняете запрос в фоновом режиме, потоке, другом компьютере, задании cron (пример: запустите запрос каждые 1 час для получения свежих результатов). Когда запрос завершен, вы можете записать в memcache все время работы системы.

Таким образом, ни одна из запросов на страницу не вызывает запрос (и, следовательно, блокирует), кроме того, вы можете постоянно/последовательно обрабатывать 100 запросов, которые вы были ранее.

Кроме того, вы не выполнили бы 100 экземпляров запроса в mysql. Он выполнил бы примерно параллельно (блокируя остальные), но остальные 90 ~ запросы будут попадать в кеш-запрос sql, поэтому он не будет буквально запускать запрос 100 раз.

Я сомневаюсь, что вы хотите работать в этом месте в любом случае.

Надеюсь, это имеет смысл!

+0

Не очень сложный запрос, я думаю, что он потребляет около 10 секунд для выполнения, но в некоторых случаях это может привести к краху сервера. Во всяком случае, ваша идея хорошая, я думаю, crontab - отличное решение. Благодарю. –

1

Моим вариантом было бы добавить дополнительный статус кеша (например, «устаревший»), чтобы пометить записи кэша, срок действия которых истек, и находятся в состоянии обновления.

Так что если php-процесс запрашивает кэшированные данные из memcached и выясняет, что его состояние «истекло», оно устанавливает состояние «устаревает», выдает новую версию из базы данных и сохраняет ее как «действительную» в Memcached.

Если другой php-процесс обращается к кешированным данным со статусом «stale», он будет просто использовать устаревшую версию, но не получит новую версию из базы данных.

Теперь, если вы хотите выжать последний бит производительности, первый процесс php не будет получать свежие данные, но вместо этого он делегирует эту задачу другому экземпляру (например, с помощью rabbitmq), а также возвращает устаревшие данные.

+0

Кажется очень разумным. Но я не понимаю, где поставить статус? Где хранить устаревший результат? Я думал, что Memcached просто очищает записи, когда они истекли. –

+0

Кстати, спасибо, что я на Rabbitmq, я до сих пор понятия не имел о таких программах. Я буду копать в руководстве, потому что к настоящему времени у меня очень размытое представление о том, как он работает. –

+0

Не используйте memcache ttl. Сохраните дату истечения срока действия и статус кеша в отдельной записи memcache. – Pierre

Смежные вопросы