php 如何缓存动态PHP页面

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3787125/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 11:06:43  来源:igfitidea点击:

How to cache dynamic PHP page

phpcaching

提问by Nagy

How to cache PHP page which has mysql query. Any example will be great and helpful.

如何缓存具有 mysql 查询的 PHP 页面。任何例子都会很棒而且很有帮助。

回答by Ken Le

I am using phpFastCache( for shared hosting, if you don't want to touch php.ini and root to setup memcached). Check out the Example Menu. They have full detail example, and very easy.

我正在使用phpFastCache(用于共享主机,如果您不想触摸 php.ini 和 root 来设置 memcached)。查看示例菜单。他们有完整的详细示例,非常简单。

First you set with phpFastCache::set and then get with phpFastCache::get - DONE!

首先使用 phpFastCache::set 进行设置,然后使用 phpFastCache::get 进行设置 - 完成!

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. With phpFastCache, your page only send 1 query to DB, and use the cache to serve 9,999 other visitors.

您的网站有 10,000 名在线访问者,并且您的动态页面必须在每次加载页面时向数据库发送 10,000 个相同的查询。使用 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
?>

回答by Annika Backstrom

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. If the page was found in cache, send it and exit rather than running the queries again.

就纯 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;
}

Obviously this needs lots of customization for your setup, including cache expiration, a $cache_keythat meets your needs, and error detection so bad pages aren't cached.

显然,这需要对您的设置进行大量自定义,包括缓存过期、$cache_key满足您的需求以及错误检测,以便不缓存坏页面。

回答by Rinku

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

    ?>

回答by sathia

memcache your html out and then do something like this:

将您的 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);

回答by Tomasz Zadora

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

PHP 不同步的典型缓存场景是这样的:如果缓存中没有资源,或者资源已过期,则必须创建并放入缓存。碰巧遇到这种情况的第一个线程/进程正在尝试创建资源,在此期间,其他线程也会创建资源,从而导致线程竞争、缓存猛烈和性能下降。

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