缓存失效

3.4 版本
维护中的版本

“计算机科学领域只有两件难事:缓存失效和命名东西”——Phil Karlton

一旦一个URL被以gateway cache方式缓存,缓存将不再针对内容而请求程序。这能令缓存提供最快的响应,并减少程序负载。但是,你面临着传送过期内容的危险。走出此困境的一种办法是使用超长缓存周期,但是当内容被更新时并不能有效通知到gateway cache。反向代理通常提供一个频道来接收这种通知,一般通过特殊的HTTP请求实现。

虽然缓存无效化是非常强大的,但还是要尽量避免它。如果你在令某些内容“无效化”时失败了,过期缓存有可能被继续提供很长一段时间。取而代之的是,使用短的缓存周期,或者使用validation模型,并调整你的控制器,令其高效地进行验证检查,如同前面通过Validation来优化代码所解释的那样。

再有,因为“失效化”对于每一种反向代理来说都是独立的话题,使用这个概念会把你拴到特定的反向代理上,或者需要额外的努力以支持这些不同的代理。

但是有时,你需要这种通过显式进行“无效化”所获得的额外性能。为了能够invalidation,你的程序需要侦测内容是何时被改变的,然后通知缓存移除包含了“从缓存中获取到该内容数据”的URLs。

如果你需要使用cache invalidation,看一下FOSHttpCacheBundle。这个bundle提供的服务通过多种cache invalidation概念来提供帮助,还对常用的缓存代理做了配置上的文档说明。

如果是一个内容对应一个URL的话,PURGE模型最为适合。你用PURGEHTTP方法发送请求给缓存代理(使用“PURGE”这个词是命名约定,技术角度讲它可是任何字符串)来替代GET,并且让缓存代理侦测到它,然后从缓存中移除数据,从而不必回到程序去获取一个响应。

下面代码演示了如何配置Symfony反向代理,以支持PURGEHTTP方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// app/AppCache.php
 
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
// ...
 
class AppCache extends HttpCache
{
    protected function invalidate(Request $request, $catch = false)
    {
        if ('PURGE' !== $request->getMethod()) {
            return parent::invalidate($request, $catch);
        }
 
        if ('127.0.0.1' !== $request->getClientIp()) {
            return new Response(
                'Invalid HTTP method',
                Response::HTTP_BAD_REQUEST
            );
        }
 
        $response = new Response();
        if ($this->getStore()->purge($request->getUri())) {
            $response->setStatusCode(200, 'Purged');
        } else {
            $response->setStatusCode(404, 'Not found');
        }
 
        return $response;
    }
}

你必须以某种方式来保护PURGEHTTP方法以避免随机用户清除你的缓存数据。

Purge指令让缓存删除一个资源,包括这资源的所有变种(根据Vary头来操作,参考前文)。另一个清除缓存的可选办法是,refreshing(刷新)一个内容。刷新的意思是,缓存代理被指示放弃其本地缓存并再次取出内容。这样做之后,新内容已经可以在缓存中使用。刷新的缺点是,并未对内容变体实施无效化。

在很多程序中,相同的内容位(content bit)被用于不同URL的多个页面中。这种情况下,还有更灵活的办法:

  • Banning 通过对URL匹配正则表达式,或其他标准,来使响应无效。

  • Cache tagging 允许你对每个用在响应中的内容添加一个标签,以便你能够令所有包含了特定内容的URL无效。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)