2

我有这样的功能:

function query($query)
{
    /* If query result is in cache already, pull it */
    if $cache->has(md5($query))
       return $cache->get(md5($query));

    /* Do the actual query here. mysqli_query() etc, whatever u imagine. */

    /* Set the cache with 10 minute expiration */
    $cache->set(md5($query), $queryOutput, array(10)); 
}

所以基本上,如果我查询SELECT * FROM USERS,它会自动缓存 10 分钟。

我不知道 md5 是否可以安全依赖。这一次,它创建了 32 个字符的字符串,这听起来有点矫枉过正。其次,已知 md5 在某些输入上给出与输出相同的字符串。是否有任何替代 md5 来识别唯一缓存键的方法?几乎没有机会,两个完全不同的 SQL 查询可能会获得相同的 md5 输出并破坏网站的某些页面,但我现在应该预测并相应地编码仍然是一个机会。

还有一件事是,我觉得这样使用函数被认为是不好的做法。USERS table在我的缓存之后可能会插入一个新用户,但SELECT * FROM USERS仍会获得相同的 md5 输出,因此,忽略新插入的用户。他们可能会在 10 分钟内多次使用相同的昵称注册。

我应该将第二个参数传递给我的敏感查询,例如query($query, 'IGNORECACHE')?对我来说这听起来不合逻辑。会有太多的事情要记住。各位大佬是怎么处理这样的问题的?

如果您能回答我关于这种情况下的 md5 替代方案的第一个问题,我将不胜感激,并且在我的第二个问题上对良好使用 SQL 缓存的简短解释将不胜感激。

谢谢你。

4

2 回答 2

4

如果您担心遇到哈希冲突(即两个查询具有相同的 md5),只需将查询本身用作键:

if $cache->has($query)
    return $cache->get($query);
$cache->set($query, $queryOutput, array(10)); 

或者,您可以使用sha1。它返回更长的字符串,因此发生冲突的机会更低。

不要担心存储 32 或 40 字节作为缓存键,这不会显着影响 Web 应用程序的性能。

MySQL 也有自己的查询缓存。如果您再次执行相同的查询,MySQL 将从其缓存中获取它。如果您将用户插入到 users 表中,MySQL 将识别出它不能再使用缓存,但您的缓存类并非如此。

于 2013-03-12T14:26:28.317 回答
2

您可以稍微安全地使用 md5,因为碰撞的几率非常低。另一个可以满足您需求的解决方案是按您的查询类型命名缓存键并使用适当的分隔符附加参数:

$result = $cache->get('userdata_'.$userId);

如果使用不小心,当数据库中的数据发生更改但旧数据仍在缓存中时,缓存会给您带来很多意想不到的问题。确保您有办法使缓存无效,并在添加/修改/删除数据时对所有相关缓存执行此操作。

于 2013-03-12T14:27:40.643 回答