【问题标题】:Generating a unique id for a given string using php使用php为给定字符串生成唯一ID
【发布时间】:2010-06-21 01:17:12
【问题描述】:

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

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

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

0->>SELECT * FROM 表 1->>从表 1、表 2 中选择 * 2->>SELECT * FROM table WHERE foo = bar

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

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

【问题讨论】:

    标签: php unique zend-cache


    【解决方案1】:

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

    例如,您可以简单地使用 MD5,它只会在 2128 种情况下产生 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])
    

    【讨论】:

    • 谢谢!我现在正在尝试。两个问题。我认为当一遍又一遍地给出相同的输入字符串时,散列应该产生相同的结果。这不正确吗? md5 散列的长度是多少,因为我认为查询本身由于生成的文件名的长度而被操作系统拒绝为 id?谢谢你,我正在尝试,但会有几个地方需要重构,所以需要一段时间。我知道我必须将查询与结果一起缓存,只是不知道怎么做!
    • 我已经在之前的评论中找到了这两个问题的答案,并在下面发布了答案。但是我仍然不确定与 md5 哈希的冲突,请有人向我解释一下。
    • @Joey:使用 MD5 和相同的字符串总是会产生相同的输出,但问题是两个 不同的 字符串有 2^128 分之一的机会也产生相同的输出。所以有可能(尽管不太可能)两个不同的查询会散列到同一个 MD5 密钥。这就是我在那里添加额外检查的原因:以确保不会发生这种情况。
    【解决方案2】:

    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);
    }
    

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

    【讨论】:

      猜你喜欢
      • 2021-07-08
      • 2011-02-03
      • 2013-02-09
      • 1970-01-01
      • 2012-06-17
      • 2011-09-24
      • 1970-01-01
      • 2018-12-10
      相关资源
      最近更新 更多