【问题标题】:PHP memcache design patternsPHP 内存缓存设计模式
【发布时间】:2010-09-24 06:37:04
【问题描述】:

我们使用 memcache 基本上是为了缓存查询结果。

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

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

无论如何,我目前正在修改我们的模型以实现这一点。

我的问题是..

我们不知道这种模式,而且我敢肯定还有其他我们不知道的模式。我已经搜索过,但无法在网络上找到任何用于实现 memcache、最佳实践等的设计模式。

谁能给我指出这样的事情,或者只是写一个例子?我想确保我们在新的重构中不会犯初学者的错误。

【问题讨论】:

标签: php design-patterns memcached


【解决方案1】:

对象缓存需要记住的一点是,它就是对象/复杂结构的缓存。很多人会错误地为直接、高效的查询而访问缓存,这会导致缓存检查/未命中的开销,而数据库本来可以更快地获得结果。

自从我教给我这条建议以来,我一直牢记在心;知道什么时候不缓存,也就是说,当开销抵消了感知的好处时。我知道它没有回答这里的具体问题,但我认为值得指出作为一般提示。

【讨论】:

    【解决方案2】:

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

    1. 为缓存记录分配一个唯一标识符(通常以某种方式取决于它缓存的数据)和任意数量的标签。
    2. 缓存记录通过其唯一标识符调用。
    3. 缓存记录可以通过其唯一标识符(一次一个)或任何标记它们的标签(可能同时使多条记录无效)失效。

    这实现起来相对简单,通常效果很好。我还没有遇到需要更多解决方案的系统,尽管可能存在一些需要特定解决方案的边缘情况。

    【讨论】:

    • 如何实现标记?您是在使用这个被黑的 memcached code.google.com/p/memcached-tag 还是在您的应用程序中使用它?可以举个例子吗?
    • 我正在使用类似于 Zend_Cache 实现方式的东西。你可以在这里阅读它 - framework.zend.com/manual/en/… 并查看实际实现的源代码
    • Zend_Cache 标签失效实现非常慢,因为它读取所有文件来检查标签。 (至少在 Zend Framework 1 版本中)
    【解决方案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;
    
    }
    

    基于查询哈希的缓存键意味着如果另一个开发人员绕过我的模型或在其他地方使用另一个函数来做同样的事情,它仍然会从缓存中提取。通常我用一对生成标记标记缓存(表的名称是一个,另一个是函数的名称)。因此,默认情况下,我们的代码在插入、删除和更新带有表标签的缓存项时无效。总而言之,缓存在我们的基本代码中是非常自动化的,开发人员可以确保缓存在我们所做的项目中“正常工作”。 (使用标记还有一个很大的副作用是我们有一个页面,它提供了细粒度的缓存清除/管理,可以选择通过模型函数或表来清除缓存)。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        mysqlnd_qc,在数据库查询结果返回级别插入memcaching,自动缓存来自mysql的结果集。它非常棒,而且是自动的。

        【讨论】:

          猜你喜欢
          • 2017-07-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-21
          • 2010-12-13
          • 2013-04-29
          • 2012-01-12
          • 1970-01-01
          相关资源
          最近更新 更多