2

我有一个项目,它是几个体育赛事系列的结果数据库。正如你想象的那样,内容或多或少保持不变。我想缓存一些内容以保存数据库查询。

该项目是使用 PHP 构建的,并且正在使用自定义 MVC。你会在哪里添加缓存逻辑?

4

5 回答 5

2

使用 Memcached。像这样,您缓存查询结果,并尝试在 DB 之前从缓存中检索。

编辑:添加了 json_encoding 数据... json_encode 比 PHP 对数组的默认序列化稍快,并且可以被其他访问数据的应用程序使用

Memcached 默认使用 FastLZ 压缩。

// The ID of the item you're looking for (from $_GET or whatever)
$id = 1;

// Create a memcached instance
$m = new Memcached();
$m->addServer('localhost', 11211);

// Try retrieving the event from memcached
$data = $m->get('event_' . $id);

if ($data) {
    // If you found data in memcached, decode it for use in code
    $data = json_decode($data);
} else {
    // If you didn't find the data in memcached, try retrieving from the DB
    $result = mysqli_query('SELECT * FROM events WHERE id = ' . $id);
    // If you found results in the DB...
    if ($data = mysqli_fetch_assoc($result)) {
        // Save them to memcached for future calls
        // Note: here, I'm using the optional param to expire it after 1 day
        $m->set('event_' . $id, json_encode($data), 86400);
    }
}
// Now you can use your data
var_dump($data);

编辑以在代码中添加注释

于 2012-11-21T16:41:18.853 回答
2

您可以在 MVC 和受 MVC 启发的设计模式中使用缓存的两点:输出和数据检索:

缓存输出:

这必须在视图中实现,作为 UI 逻辑的一部分(视图应该是实例,而不仅仅是哑模板)。某处是视图在响应中组合模板的同一区域。只有在这种情况下,一些“模板”实际上是完全没有变量的。

通过这种方式,您可以在 MVC 的上下文中缓存 HTML 片段 .. 但这不适用于您的特定用例。它更适合与数据源交互花费太多时间的情况。就像存储实际上是 REST API 一样。

缓存数据:

要启用此功能,必须在模型层中执行。准确地说:在服务中(类/实例,主要包含域和存储逻辑之间的交互)。

如果你有一个完全实现的模型层,你在其中分离应用程序、域和存储逻辑,那么缓存的实现看起来就像是不同的存储形式。

$user = new User;
$cache = new UserCacheMapper;
    
$user->setId( 42 );
if ( ! $cache->fetch( $user ) )
{
    $storage = new UserSQLMapper( $pdo );
    $storage->fetch( $user );

    $cache->store( $user );
}

// the $user object has been initialized

对象的初始化实际上应该由服务内的工厂执行,但这是一个简化的示例

通过这种方式,您可以在不使用缓存的情况下创建应用程序,并且仅在以后通过修改服务(负责应用程序逻辑)来添加它。域对象(域逻辑)和数据映射器(存储逻辑)都不必改变。

于 2012-11-21T16:54:51.113 回答
1

我会使用 memcached,因为它非常容易使用它来构建缓存解决方案http://memcached.org/

我通常将缓存逻辑放在控制器中,尽管模型通常可能更适合它,原因是模型使用的上下文会影响缓存策略

将其放入模型中会使缓存策略与正确的其余数据访问功能保持一致,这意味着您可以交换模型并且缓存代码随之移动。这可能会失败的地方是您有无法放入模型中的复杂失效。

“计算机科学中只有两件困难的事情:缓存失效和命名”Phil Karlton

于 2012-11-21T16:38:19.163 回答
1

可以使用 Memcache(d) 缓存对象,这对于多服务器设置最有用。对于单个服务器,您可以将内容存储在提供缓存设施的 APC/Xcache 等中。

我会在数据访问方法中缓存数据。

于 2012-11-21T16:41:29.760 回答
1

您说您正在使用自己的 MVC 模式框架,因此很难给出具体的建议。

有几个地方可以缓存。

如果您正确使用 HTTP(幂等性、etag、缓存控制标头等),您可能会受益于将缓存层放置在应用程序之外并使用像varnish这样的前向缓存来缓存整个页面。但是,很容易弄错 HTTP,所以这可能不是要走的路。例如,如果您有用户帐户,并且相同的 url 根据登录的用户产生不同的服务器输出,则不能使用 HTTP 缓存,因为您的资源取决于 cookie 状态。(您应该做的是将用户放入 url,例如,/mysite/{userid}/profile而不是/mysite/profile。)您可能仍然可以通过其更高级的功能使用 varnish,但这会更加困难。

你说你只是对缓存数据库查询结果感兴趣,所以我会解决这个问题。

如果您有一些定义明确的查询想要缓存数据库响应,您可以将逻辑放在控制器中:在将模型传递给视图之前,显式缓存它。如果您有多个缓存位置,此解决方案会产生混乱的代码库。此外,如果您在不同的控制器中检索相同的数据,则需要仔细并手动确保检索相同模型的所有控制器代码也查询缓存并使用相同的缓存键。显然,打开和关闭缓存也变得困难。

更简洁的解决方案是以透明缓存结果的方式包装模型。这意味着您可以以声明方式添加缓存,而无需对控制器或模型进行重大更改。但是,这需要一个设计良好的模型 api,而您可能没有。

于 2012-11-21T16:59:36.467 回答