我想基于引用计数在PHP中实现数据库缓存功能。例如,访问ID为{1的表foo
中的记录的代码可能如下所示:
$fooRecord = $fooTable->getRecord(1);
第一次调用它时,$fooTable
从数据库中提取相应的记录,将其存储在内部缓存中并返回。对getRecord(1)
的任何后续调用都将返回对内存中同一对象的另一个引用。 $fooRecord
在它构造时发出$fooTable
信号,如果没有剩余的引用,它会将所有更改存储回数据库并将其从缓存中删除。
问题是PHP的内存管理抽象了有关引用计数的细节。我已经搜索了PECL和Google的扩展程序,但没有找到任何结果。所以问题#1是:这样的扩展是否存在?
在另一种方法中,$ fooTable返回一个超级偷偷摸摸的假对象。它通过转发__call()
,__set()
和__get()
来伪装成记录,并且其构造函数和析构函数提供适当的钩子以用于引用计数。测试,效果很好,除了打破类型提示。我所有期待FooRecord对象的方法现在都得到了一个Sneaky对象,或者如果我想为我的每个表创建一个空的Sneaky子类,可能是FooSneaky,我不这样做。另外,我担心它会让维护程序员(比如我自己)感到困惑。
问题2:我错过了另一种方法吗?
答案 0 :(得分:2)
对于php5,只需使用记录类中的析构函数。
class Table {
/* [...] */
protected $record_cache = array();
public function getRecord($id) {
if(isset($this->record_cache[$id]) return $this->record_cache[$id];
$r = $db->getRecord($id);
if($r instanceof Record) {
$this->record_cache[$id] = $r;
}
return $r;
}
public function _unregister($id) {
unset($this->record_cache[$id]);
}
}
class Record {
/* [...] */
function __destruct() {
this->table->_unregister($this->id);
}
}
如果你不想在Table中有一个公共方法,你可能会使用一些回调技巧或其他一些聪明的黑客:)
答案 1 :(得分:1)
您是否看过PHP中的简单缓存实现?例如,使用类似Zend_Cache的内容:
public function getRecord($id) {
$cache = $this -> getCache(); //Retrieves an instanced Zend_Cache object or creates one
$key = $this -> _name . $id; //_name is the table name and with the ID create a unique key
if(!$result = $cache->load($key)) {
//Cache miss, query database
$result = $this -> query(...);
$cache->save($result, $key);
}
return $result;
}
您可以自己轻松实现此缓存功能,或使用Zend的就绪组件。
答案 2 :(得分:1)
标准互联网帮助论坛警告:我可能不完全了解您要做的事情。
我不确定你的想法是否适合PHP的请求/响应周期。传统上(CGI,mod_php),PHP请求的生命周期看起来像
这是PHP在市场上表现良好且缺乏经验的程序员的原因之一。即使是最可怕的编码应用程序也只能在请求的生命周期中挂起服务器。与HTTP有一些相似之处;构建PHP是为了使每个请求都不知道任何其他请求。
我不熟悉fast-cgi部署技术(例如在Zend平台中使用),但据我所知,多个PHP进程将在内存中挂起来处理请求,然后有一些神奇的伏都教去这将根据需要杀死并重新生成进程。
所有这一切的重点是,通过引用计数跟踪PHP对象在内存中的位置的想法对PHP请求模型没有意义,这就是为什么你没有找到那么多。在PHP用户空间中缓存意味着使用单独的可编程系统,沿着memcached或APC的行来处理内存管理的细节。缓存被抽象为一个简单的键/值对存储系统。
那就是说,如果你向前推进你的方法,我会对看到最终结果感兴趣:)
答案 3 :(得分:0)