0

我使用 Zend_Cache_Core 和 Zend_Cache_Backend_File 来缓存为访问数据库的模型类执行的查询结果。

基本上,查询本身应该形成用于缓存获得的结果的 id,唯一的问题是它们太长了。Zend_Cache_Backend_File 不会抛出异常,PHP 不会抱怨,但不会创建缓存文件。

我想出了一个根本没有效率的解决方案,将任何执行的查询与自动递增的 id 一起存储在一个单独的文件中,如下所示:

0->>SELECT * FROM table 1->>SELECT * FROM table1,table2 2->>SELECT * FROM table WHERE foo = bar

你明白了;这样我每个查询都有一个唯一的 ID。每当插入、删除或更新完成时,我都会清除缓存。

现在我确定您在这里看到了潜在的瓶颈,对于任何测试,从缓存中保存或获取两个(或三个,我们需要添加一个新的 id)请求都会向文件系统发出。这甚至可能会破坏所有缓存的需要。那么有没有一种方法可以在 php 中生成一个唯一的 id,即更短的表示形式,而不必将它们存储在文件系统或数据库中?

4

2 回答 2

1

字符串是任意长的,因此显然不可能创建一个可以表示任意输入字符串而不重复的固定大小的标识符。但是,出于缓存的目的,您通常可以使用简单的“足够好”的解决方案并将冲突减少到可接受的水平。

例如,您可以简单地使用 MD5,它只会在 2 128个案例中产生 1 个碰撞。如果您仍然担心冲突(为了安全起见,您可能应该这样做),您可以将查询结果存储在缓存的“值”中,并检查何时返回值,它实际上是查询你在找。

举个简单的例子(我的 PHP 有点生疏,但希望你能明白):

$query = "SELECT * FROM ...";

$key = "hash-" + hash("md5", $query);
$result = $cache->load($key);
if ($result == null || $result[0] != $query) {
    // object wasn't in cache, do the real fetch and store it
    $result = $db->execute($query); // etc

    $result = array($query, $result);
    $cache->save($result, $key);
}

// the result is now in $result[1] (the original query is in $result[0])
于 2010-06-21T01:28:23.090 回答
0

MD5!!

Md5 生成一个长度为 32 的字符串,似乎工作正常,创建了缓存文件(文件名的长度约为 47),因此操作系统似乎没有拒绝它们。

//returns id for a given query
function getCacheId($query) {
    return md5($query);
}

就是这样!但是存在冲突的问题,我认为对 md5 哈希进行加盐(可能使用表的名称)应该使其更加健壮。

//returns id for a given query
function getCacheId($query, $table) {
    return md5($table . $query);
}

如果有人想要我如何实现结果缓存的完整代码,请发表评论,我很乐意发布。

于 2010-06-21T02:52:40.613 回答