#php #postgresql #memcached #simultaneous
#php #postgresql #memcached #одновременный
Вопрос:
Скорее всего, я буду использовать MemCache для кэширования некоторых результатов базы данных. Поскольку я никогда не писал и не выполнял кэширование, я подумал, что было бы неплохо спросить тех из вас, кто уже это делал. В системе, которую я пишу, в какой-то момент времени могут выполняться сценарии параллелизма. Это то, что я планирую сделать:
- Я пишу систему обмена баннерами.
- Информация о баннерах хранится в базе данных.
- Существуют разные сайты с разным трафиком, загружающие php-скрипт, который генерирует код для этих баннеров. (чтобы баннеры отображались на сайте клиента)
- Когда баннер отображается в первый раз — он кэшируется с помощью memcache.
- Время жизни баннера в кэше составляет, например, 1 час.
- Кэш обновляется каждый час.
Потенциальная проблема, которую я вижу в этой задаче, находится на шагах 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. Еще раз спасибо за помощь, Джимми! Все кажется совершенно логичным 🙂