Потенциальные проблемы с PHP Memcache?

#php #postgresql #memcached #simultaneous

#php #postgresql #memcached #одновременный

Вопрос:

Скорее всего, я буду использовать MemCache для кэширования некоторых результатов базы данных. Поскольку я никогда не писал и не выполнял кэширование, я подумал, что было бы неплохо спросить тех из вас, кто уже это делал. В системе, которую я пишу, в какой-то момент времени могут выполняться сценарии параллелизма. Это то, что я планирую сделать:

  1. Я пишу систему обмена баннерами.
  2. Информация о баннерах хранится в базе данных.
  3. Существуют разные сайты с разным трафиком, загружающие php-скрипт, который генерирует код для этих баннеров. (чтобы баннеры отображались на сайте клиента)
  4. Когда баннер отображается в первый раз — он кэшируется с помощью memcache.
  5. Время жизни баннера в кэше составляет, например, 1 час.
  6. Кэш обновляется каждый час.

Потенциальная проблема, которую я вижу в этой задаче, находится на шагах 4 и 6. Если у нас есть, например, 100 сайтов с большим трафиком, может случиться, что скрипт имеет несколько экземпляров, запущенных одновременно. Как я могу гарантировать, что по истечении срока действия кэша он будет восстановлен один раз и данные останутся нетронутыми?

Ответ №1:

Как я могу гарантировать, что по истечении срока действия кэша он будет восстановлен один раз и данные останутся нетронутыми?

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

 // returns false if there is no value or the value is expired
result = cache_check(key)

if (!result)
{
    result = fetch_from_db()

    // set it for next time, until it expires anyway
    cache_set(key, result, expiry)
}
  

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

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

Комментарии:

1. В моей ситуации, однако, у кэша должно быть время истечения срока действия, потому что нет никаких операций, которые пользователи могли бы выполнить вместо того, чтобы гипотетически читать «чтение комментариев». Спасибо за информацию! 🙂

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

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

4. Это вообще не должно быть проблемой — они оба, как вы сказали, будут считываться из источника данных, и один перезапишет другой. Это не проблема, пока вы не выполняете зависимые операции (например, увеличиваете значения кэша и т.д.). Пока вы просто собираете данные и кэшируете их, эти данные должны быть одинаковыми за этот короткий промежуток времени. Если это не так, ограничьте границы ваших данных, чтобы это был предсказуемый интервал, с которым вы кэшируете (поэтому, если вы запускаете скрипт в 12 часов ночи, учитывайте только данные, созданные до 11:59: 59 вечера).

5. Еще раз спасибо за помощь, Джимми! Все кажется совершенно логичным 🙂