Как кэшировать динамическую страницу PHP

Как кэшировать страницу PHP с запросом mysql. Любой пример будет большим и полезным.

Я использую phpFastCache (для общего хостинга, если вы не хотите прикасаться к php.ini и root для установки memcached). Проверьте меню примеров. У них есть подробный пример и очень простой.

Сначала вы устанавливаете с phpFastCache :: set, а затем получаете с phpFastCache :: get-DONE!

Пример: сокращение запросов к базе данных

На вашем сайте 10 000 посетителей, которые подключены к сети, и ваша динамическая страница должна отправлять 10 000 одинаковых запросов в базу данных при каждой загрузке страницы. С phpFastCache ваша страница отправляет только 1 запрос в БД и использует кеш, чтобы обслуживать 9999 других посетителей.

<?php // In your config file include("php_fast_cache.php"); phpFastCache::$storage = "auto"; // you can set it to files, apc, memcache, memcached, pdo, or wincache // I like auto // In your Class, Functions, PHP Pages // try to get from Cache first. $products = phpFastCache::get("products_page"); if($products == null) { $products = YOUR DB QUERIES || GET_PRODUCTS_FUNCTION; // set products in to cache in 600 seconds = 5 minutes phpFastCache::set("products_page",$products,600); } OUTPUT or RETURN your $products ?> 

Мое предпочтение заключается в использовании кэширующего обратного прокси-сервера, такого как Varnish .

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

 <?php function cache_file() { // something to (hopefully) uniquely identify the resource $cache_key = md5($_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']); $cache_dir = '/tmp/phpcache'; return $cache_dir . '/' . $cache_key; } // if we have a cache file, deliver it if( is_file( $cache_file = cache_file() ) ) { readfile( $cache_file ); exit; } // cache via output buffering, with callback ob_start( 'cache_output' ); // // expensive processing happens here, along with page output. // function cache_output( $content ) { file_put_contents( cache_file(), $content ); return $content; } 

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

memcache ваш html и затем сделать что-то вроде этого:

 $memcache = memcache_connect('localhost', 11211); $page = $memcache->get('homepage'); if($page == ""){ $mtime = microtime(); $page = get_home(); $mtime = explode(" ",$mtime); $mtime = $mtime[1] + $mtime[0]; $endtime = $mtime; $totaltime = ($endtime - $starttime); memcache_set($memcache, 'homepage', $page, 0, 30); $page .= "\n<!-- Duly stored ($totaltime) -->"; } else{ $mtime = microtime(); $mtime = explode(" ",$mtime); $mtime = $mtime[1] + $mtime[0]; $endtime = $mtime; $totaltime = ($endtime - $starttime); $page .= "\n&lt;!-- served from memcache ($totaltime) -->"; } die($page); 
  <?php //settings $cache_ext = '.html'; //file extension $cache_time = 3600; //Cache file expires afere these seconds (1 hour = 3600 sec) $cache_folder = 'cache/'; //folder to store Cache files $ignore_pages = array('', ''); $dynamic_url = 'http://'.$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']; // requested dynamic page (full url) $cache_file = $cache_folder.md5($dynamic_url).$cache_ext; // construct a cache file $ignore = (in_array($dynamic_url,$ignore_pages))?true:false; //check if url is in ignore list if (!$ignore && file_exists($cache_file) && time() - $cache_time < filemtime($cache_file)) { //check Cache exist and it's not expired. ob_start('ob_gzhandler'); //Turn on output buffering, "ob_gzhandler" for the compressed page with gzip. readfile($cache_file); //read Cache file echo '<!-- cached page - '.date('l jS \of FY h:i:s A', filemtime($cache_file)).', Page : '.$dynamic_url.' -->'; ob_end_flush(); //Flush and turn off output buffering exit(); //no need to proceed further, exit the flow. } //Turn on output buffering with gzip compression. ob_start('ob_gzhandler'); ######## Your Website Content Starts Below ######### ?> <!DOCTYPE html> <html> <head> <title>Page to Cache</title> </head> <body> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ut tellus libero. </body> </html> <?php ######## Your Website Content Ends here ######### if (!is_dir($cache_folder)) { //create a new folder if we need to mkdir($cache_folder); } if(!$ignore){ $fp = fopen($cache_file, 'w'); //open file for writing fwrite($fp, ob_get_contents()); //write contents of the output buffer in Cache file fclose($fp); //Close file pointer } ob_end_flush(); //Flush and turn off output buffering ?> 

Важная вещь, которую часто упускают из виду при обсуждении кеширования, – это синхронизация процесса, чтобы избежать гонки потоков (см. https://en.wikipedia.org/wiki/Race_condition ).

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

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

Существует очень мало систем кэширования для PHP, которые учитывают его синхронизацию.

Один из них – php-no-slam-cache: https://github.com/tztztztz/php-no-slam-cache