Intereting Posts
Как запустить скрипт оболочки в PHP? Перенаправление после входа в систему, URL-адреса WordPress Несколько возвратов из функции Ошибка TokenMismatch для запросов Ajax в Laravel nohup: запустить PHP-процесс в фоновом режиме Как добавить пользовательские заголовки в https, запрашивая скрипт PHP? Каков наилучший способ встраивания видео Youtube? Предупреждение: file_get_contents не удалось открыть поток: время ожидания подключения включает / simple_html_dom.php в строке 75 Предупреждение: mysqli_fetch_assoc () ожидает, что параметр 1 будет mysqli_result, boolean задан в C: \ xampp \ htdocs \ xyz \ userpanel.php в строке 71 Как объединить два массива, взяв только значения из второго массива с теми же ключами, что и первый? Как получить список сообщений и связанные теги с наименьшим количеством запросов Включая общий html-заголовок на всех страницах сайта на 20 страницах (с активным классом) Взломанный, что делает этот кусок кода? больше параметров с функцией mail () строка поиска не работает при использовании mysqli

Каким образом можно управлять ключами (в memcache) для предотвращения устаревших кешированных значений?

Недавно я реализовал memcache на моем сайте, который был под тяжелой загрузкой mysql (mysql был так же оптимизирован, как я мог это сделать). Он решил все мои проблемы с загрузкой, и сайт работает красиво.

Проблема, с которой сейчас сталкивается Im, – это устаревшие кешированные значения. У меня есть время истечения времени в 1 час на большинстве страниц, и я также удаляю ключ, когда значение в блоках DB, но Im с трудом отслеживает и эффективно очищает все ключи.

На некоторых страницах это тривиально. Я могу сделать ключ item_id (например, item_4653), и когда данные для него обновляются или элемент удаляется, ключ очищается.

Но на большинстве страниц я беру скрипт filename + querystring, md5 и использую его как ключ в memcache. Это особенно полезно для сложных URL-адресов (которые очень распространены).

Например, у меня загружена следующая страница.

index.php? search_keywords = good & search_section = 1 & sort = release & page = 2

Он будет содержать список элементов, которые будут извлекаться из memcache. Затем другой пользователь отправляет элемент, который имеет « хороший » в своем названии, и он находится в диапазоне значений, где он появится на стр. 2, за исключением того, что он не появится там, пока не будет обновлен кеш. Что еще более усложняет, так это то, что вновь добавленный элемент также появится на index.php? Sort = newest, а также index.php? Category = some_category? Page = 1 и т. Д. Каждый из них будет иметь уникальную key (md5 имени скрипта + строка запроса).

Таким образом, новый добавленный элемент может отображаться на десятках страниц, если они были извлечены из живой БД, но он не будет виден ни на одном из них, пока не будет обновлен устаревший кеш. Единственный вариант – дождаться истечения срока действия элемента.

Эта проблема становится еще более выраженной на моем форуме (пользовательская кодировка), где значения HAVE должны быть обновлены по требованию для всех возможных кеш-комбинаций страниц. Допустим, у меня 4 страницы, и я замечаю 3 спам-сообщения на странице 2. После их удаления страница 2 перестраивается, но затем она также должна перестраивать страницы 3 и 4, в противном случае будут дублироваться сообщения на новой странице восстановления 2 , и старая страница 3. Это просто пример для ….. Есть десятки этих сценариев.

Есть идеи?

Поскольку вы кэшируете целые страницы в memcached, ваши страницы не могут передавать кэшированные данные из базы данных друг с другом. Скажем, у меня есть page1.php и page2.php, а страницы1 и page2 – как ключи в memcached. Обе страницы отображают элементы . Я добавляю новый элемент. Теперь я должен истечь страницы 1 и стр . 2.

Вместо этого у меня мог бы быть ключ элементов в memcached, который page1.php и page2.php используют для отображения элементов. Когда я добавляю новый элемент, я теряю ключ элементов (или, лучше, обновляю его значение), и оба page1.php и page2.php обновлены.

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

"page1:[timestamp of newest item]" 

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

Вы можете использовать более простую схему именования для своих ключей memcached, поэтому их проще удалить. Похоже, что с решением MD5 вы можете создавать слишком много ключей для вещей, которые обычно показывают одни и те же данные.

Вы могли бы также рассмотреть более короткое время кеша, например, 20 минут?

Также – сколько элементов на странице вы извлекаете для каждой из этих страниц результатов поиска? Если у вас есть разбитый на страницы поиск – получение 50 элементов с сервера не должно быть слишком интенсивным.

Возможно, вы настроили сервер mysql, но настроили ли вы запросы (улучшив их, просмотрев вывод EXPLAIN) или структуры таблиц (добавив полезные индексы)?

Мне также интересно, насколько интенсивны запросы на этих страницах. Вы присоединяетесь к нескольким столам? Вы можете воспользоваться более простым запросом или несколькими запросами (описанными ниже).

Альтернативно. Для каждой строки результата вы запускаете другой запрос – или несколько? Вы можете воспользоваться немного более сложным поисковым запросом, который позволяет вам выполнять вложенные запросы. Или вы укушены библиотекой ORM, которая делает то же самое, запускает поиск, а затем запросы для подпунктов на каждой итерации?

«Несколько простых запросов» – скажем, например, – если у вас есть элемент и вы хотите узнать его категорию в наборе результатов …

Вместо этого:

 SELECT i.id, i.name, c.category FROM items AS i INNER JOIN categories AS c ON i.category_id = c.id; 

Это простой пример – но, скажем, были категории и несколько других JOINs.

Вы можете пойти по этому маршруту:

 // run this query SELECT id, category FROM categories - and put that into a keyed array. // then in PHP create an array keyed by the id $categories = array(); while ( false !== ( $row = mysql_fetch_assoc ( $result ) ) ) { $categories[ $row['id'] ] = $row['category']; } // and so on $types = array(); // ... // etc. 

Затем выполните поиск, но без всех JOINS, только из таблицы элементов с вашими предложениями, а в выводе …

 <?php foreach($items as $item): ?> <h4><?php echo $item['name']; ?></h4> <p>Category: <?php echo $categories[ $item['category_id'] ]; ?></p> <p>Type: <?php echo $types[ $item['type_id'] ]; ?></p> <!-- and so on --> <?php endforeach; ?> 

Это небольшое гетто, но, возможно, это – и другие предложения – помогут.

Memcached :: set имеет параметр expire. Возможно, вы можете оставить это значение по умолчанию в течение часа, но для страниц, возвращающих результаты поиска, или на вашем форуме, вы можете установить это на более короткий период времени.

Пара простых вещей, которые вы можете сделать:

Во-первых, если вы действительно хотите использовать строку запроса в качестве ключа кэша, сделайте ее более детерминированной и предсказуемой. Я бы сделал это, отсортировав строку запроса, например ?zed=7&alpha=1 преобразуется в ?alpha=1&zed=7 . Также отключите переменные, которые не относятся к ключу кеширования.

Чтобы справиться с проблемой параметра? Page, а элементы не отображаются, потому что кеш не обновился, у меня есть пара идей:

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

Другим подходом было бы хранить количество страниц в значении кеша, а затем, когда база данных обновляется, итерации через ключи кеша.

 cache.put("keyword,page=3", array(num_pages=7, value=...)) ...later... update_entry() num_pages, value = cache.get("keyword,page=3") for i in num_pages: cache.flush("keyword,page="+i) 

Является ли это хорошей идеей или нет, зависит от того, сколько страниц есть, и вероятность появления обновлений во время цикла.

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

 cache.put("keyword", array(0="bla", 1=foo", ...) ...later... cache.get("keyword")[page_num] 

Четвертая идея состоит в том, чтобы изменить ваш сервер кэширования и использовать что-то построенное для обработки этой ситуации. Я не знаю, какие еще кэш-серверы там, поэтому вам придется осмотреться.

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

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

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

Идея состоит в том, чтобы в основном иметь номер версии, хранящийся в memcache, в вашем случае определенное ключевое слово (за ключ, а не комбинацию). Как это использовать?

Когда кто-то отправляет новый элемент:

  • для каждого слова в заголовке, if(!Memcache:increment("version_" + keyword)) {Memcache:set("version_" + keyword);}

Когда кто-то выполняет запрос:

  • вещь md5, которую вы делаете, уже хорошо. Кроме того, вам нужно добавить версию каждого ключевого слова в строку поиска к ключу memcache.

Это гарантирует, что как только ключевое слово будет иметь новые результаты (или меньше при удалении), версия столкнется и, как таковая, все связанные запросы memcache.

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

недействительность кэша – большая проблема

«В информатике есть только две серьезные проблемы: недействительность кеша и именование вещей».

Я дам вам несколько идей, которые приведут вас к полному решению, поскольку для всех вариантов использования нет генрального решения ..

  • читать о лаки esi и X-Article-id https://www.varnish-software.com/blog/advanced-cache-invalidation-strategies
  • использовать nginx ssi
  • отслеживать все ваши элементы в кеше, поэтому, если вы кэшируете 100 сообщений форума, сохраняйте каждый из идентификаторов сообщений в db, чтобы у вас было что-то вроде lastMessages, содержащее сообщения: 1,2,550,123 и т. д. теперь, когда любой из элементов получает обновленный поиск, где его хранить и чистить их один за другим (или восстанавливать их и хранить снова)
  • его, как одно и то же решение, но вместо каждого элемента кэша знают, что его магазин, каждая модель должна знать, где его магазин