简体   繁体   English

如何缓存动态PHP页面

[英]How to cache dynamic PHP page

How to cache PHP page which has mysql query. 如何缓存具有mysql查询的PHP页面。 Any example will be great and helpful. 任何一个例子都会很有帮助。

I am using phpFastCache ( for shared hosting, if you don't want to touch php.ini and root to setup memcached). 我正在使用phpFastCache (用于共享主机,如果你不想触摸php.ini和root来设置memcached)。 Check out the Example Menu. 查看示例菜单。 They have full detail example, and very easy. 他们有完整的详细示例,非常简单。

First you set with phpFastCache::set and then get with phpFastCache::get - DONE! 首先你用phpFastCache :: set设置然后用phpFastCache :: get - DONE获取!

Example: Reduce Database Calls 示例:减少数据库调用

Your website have 10,000 visitors who are online, and your dynamic page have to send 10,000 same queries to database on every page load. 您的网站有10,000名在线访问者,您的动态页面必须在每次加载页面时向数据库发送10,000个相同的查询。 With phpFastCache, your page only send 1 query to DB, and use the cache to serve 9,999 other visitors. 使用phpFastCache,您的页面只向DB发送1个查询,并使用缓存为9,999个其他访问者提供服务。

<?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
?>

My preference is to use a caching reverse proxy, like Varnish . 我的偏好是使用缓存反向代理,如Varnish

As far as a pure PHP solution, you could have some code at the end of your script that caches the final output, and code at the beginning that checks to see if the page is cached. 就纯PHP解决方案而言,您可以在脚本末尾放置一些缓存最终输出的代码,并在开头检查以查看页面是否缓存。 If the page was found in cache, send it and exit rather than running the queries again. 如果在缓存中找到该页面,则发送它并退出而不是再次运行查询。

<?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;
}

Obviously this needs lots of customization for your setup, including cache expiration, a $cache_key that meets your needs, and error detection so bad pages aren't cached. 显然,这需要对您的设置进行大量自定义,包括缓存过期,满足您需求的$cache_key以及错误检测,以便不缓存错误的页面。

    <?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 F Y 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

    ?>

memcache your html out and then do something like this: 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);

The important thing, often overlooked when there is discussion about caching, is process synchronization to avoid thread race (see: https://en.wikipedia.org/wiki/Race_condition ). 在讨论缓存时经常忽略的重要事情是进程同步以避免线程竞争(请参阅: https//en.wikipedia.org/wiki/Race_condition )。

Typical caching scenario in PHP without synchronization looks like this: if you don't have resource in the cache, or resource is expired, it must be created and put into cache. PHP中没有同步的典型缓存方案如下所示:如果缓存中没有资源,或者资源已过期,则必须创建它并将其放入缓存中。 First thread/process that happens to encounter such condition is trying to create resource, and during that time, other threads will also create the resource, which leads to thread race, cache slamming and performance downspike. 碰巧遇到这种情况的第一个线程/进程正在尝试创建资源,在此期间,其他线程也将创建资源,这会导致线程争用,缓存砰击和性能下降。

Problem is magnified by number of concurrent threads and workload created by resource creation task. 问题由资源创建任务创建的并发线程数和工作负载数放大。 On busy systems it may lead to serious problems. 在繁忙的系统上,它可能会导致严重的问题。

There is very few caching systems for PHP that takes it into consideration synchronization. PHP的缓存系统很少考虑同步。

One of them is php-no-slam-cache: https://github.com/tztztztz/php-no-slam-cache 其中一个是php-no-slam-cache: https//github.com/tztztztz/php-no-slam-cache

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM