PHP memcache设计模式

时间:2008-11-27 01:33:20

标签: php design-patterns memcached

我们基本上只使用memcache来缓存查询结果。

由于实施方式,失效是一场噩梦。我们通过阅读邮件列表学习了一些memcache技术,例如允许组失效的技巧。对于那些知道它的人,请跳过下一段..

对于那些不知道并且感兴趣的人,诀窍是为您的密钥添加序列号并将该序列号存储在memcache中。然后每次在你“获取”之前,你都会抓住当前的序列号并围绕它建立你的密钥。然后,为了使整个组无效,您只需递增该序列号。

所以无论如何,我正在修改我们的模型来实现它。

我的问题是......

我们不知道这种模式,我确信还有其他我们不知道的模式。我已经搜索过,并且无法在网上找到任何设计模式来实现内存缓存,最佳实践等。

有人能指出我这样的事情,甚至只是写一个例子吗?我想确保在新的重构中我们不会让初学者犯错。

5 个答案:

答案 0 :(得分:15)

使用对象缓存记住的一点是,它就是 - 对象/复杂结构的缓存。许多人犯了错误,他们会在简单有效的查询中点击他们的缓存,这会导致缓存检查/未命中的开销,此时数据库可以更快地获得结果。

这条建议是我向他们传授的一个忠告;知道什么时候不要缓存,也就是说,当开销取消了感知的好处时。我知道这里没有回答具体问题,但我认为值得指出这是一个普遍的暗示。

答案 1 :(得分:6)

抢劫说的是好建议。根据我的经验,识别和使标签无效的方法有两种:唯一标识和基于标签的标识。这些通常组合在一起形成一个完整的解决方案,其中:

  1. 为缓存记录分配一个唯一标识符(通常以某种方式取决于它所缓存的数据)以及可选的任意数量的标记。
  2. 缓存记录由其唯一标识符调用。
  3. 缓存记录可以通过其唯一标识符(一次一个)或通过标记它们的任何标记(可能同时使多个记录无效)失效。
  4. 这实现起来相对简单,通常效果很好。我还没有遇到需要更多的系统,尽管可能有一些边缘情况需要特定的解决方案。

答案 2 :(得分:3)

我使用Zend Cache组件(如果需要,您不必使用整个框架只是zend缓存的东西)。它抽象了一些缓存内容(它支持通过'标签'对缓存进行分组,尽管memcache后端不支持该功能我已经相对轻松地支持我对'标签'的支持)。因此,我用于访问缓存(通常在我的模型中)的函数的模式是:

public function getBySlug($ignoreCache = true)
{
    if($ignoreCache || !$result = $this->cache->load('someKeyBasedOnQuery'))
    {
        $select = $this->select()
                ->where('slug = ?', $slug);
        $result = $this->fetchRow($select);

        try
        {
            $this->cache->save($result,'someKeyBasedOnQuery');
        }
        catch(Zend_Exception $error)
        {
          //log exception
        }
    }
    else
    {
        $this->registry->logger->info('someKeyBasedOnQuery came from cache');
    }
    return $result;

}

将缓存键置于查询的散列上意味着如果另一个开发人员绕过我的模型或在其他地方使用另一个执行相同操作的函数,它仍然会从缓存中提取。通常我用一对generate标记标记缓存(表的名称是一个,另一个是函数的名称)。因此,默认情况下,我们的代码在插入,删除和更新带有表标记的缓存项时无效。总而言之,我们的基本代码中的缓存非常自动,开发人员可以确保缓存在我们所执行的项目中“正常工作”。 (使用标记的巨大副作用是我们有一个页面提供精细的缓存清除/管理,可以选择通过模型函数或表清除缓存)。

答案 3 :(得分:1)

我们还将来自数据库(PostgreSQL)的查询结果存储在memcache中,我们在表上使用触发器使缓存无效 - 那里有几个API(例如pgmemcache,我认为mysql有类似的东西那也是我不确定的。)好处是数据库self(触发器)可以处理更改(更新,插入,删除)上的数据失效,您不需要将所有内容写入“应用程序”。

答案 4 :(得分:0)

mysqlnd_qc,它在数据库查询结果返回级别插入memcaching,从mysql自动缓存结果集。这很神奇,很自动。