Php 如何基于多个参数进行缓存

Php 如何基于多个参数进行缓存,php,caching,Php,Caching,我正在开发一个搜索应用程序,该应用程序使用具有16个筛选选项的表单,这些选项为1(已选择)或0(未选择)。通过AJAX使用GET请求检索JSON结果 查询字符串如下所示: 筛选器_1=0和筛选器_2=1…省略&过滤器16=1和页面=20 每个搜索结果至少有2个页面可供用户浏览 我的问题是:如何根据输入参数缓存搜索结果?我的第一个想法是md5 requestparameters,然后使用哈希作为文件名编写缓存文件 每次传入新请求时,我都会搜索缓存文件,如果存在,则使用该文件中的数据,而不是查询数据

我正在开发一个搜索应用程序,该应用程序使用具有16个筛选选项的表单,这些选项为1(已选择)或0(未选择)。通过AJAX使用GET请求检索JSON结果

查询字符串如下所示:

筛选器_1=0和筛选器_2=1…省略&过滤器16=1和页面=20

每个搜索结果至少有2个页面可供用户浏览

我的问题是:如何根据输入参数缓存搜索结果?我的第一个想法是md5 requestparameters,然后使用哈希作为文件名编写缓存文件

每次传入新请求时,我都会搜索缓存文件,如果存在,则使用该文件中的数据,而不是查询数据库并将行转换为json结果

但这似乎不是一个好主意,因为有很多搜索选项。将有相当多的缓存文件(16*16??),并且由于应用程序仅由少数用户使用,我怀疑所有可能的组合是否都会被缓存。每个结果都包含X个页面,因此每个页面都是自己的缓存文件(16*16*X)


对于这样的应用程序,什么是好的缓存策略?实际上可以实现缓存吗?

为什么需要缓存


如果应用程序仅由少数用户使用,那么实际上可能不需要缓存

考虑到您描述的需求(少量用户),在我看来,缓存所有组合似乎是合理的。当然,除非缓存是有意义的。一个典型的查询需要多长时间?既然你说这个应用程序只能由几个人使用,那么它值得缓存吗?我的粗略估计是,如果在这种情况下查询不需要几秒钟,就不用担心缓存。如果时间不到一秒,并且您真的不想让应用程序具有超级响应性,则不需要缓存


否则,我会说(同样考虑到少量用户),缓存所有组合是可以的。即使使用了大量的文件,也最多有65536个,许多现代操作系统可以轻松处理目录中的数千个文件(以防您计划缓存到文件中)。但在任何情况下,限制缓存中的项目数量并定期清除旧项目都是合理的。另外,我不使用MD5,我只会把你的过滤器中的零点和零点连接到缓存键(例如0101100010010100)。

< P>因为你所有的搜索参数都是0或1的标志,你可以考虑位错。 每个过滤器将表示一个2的幂次值:

$filter_1 = 1;
$filter_2 = 2;
$filter_3 = 4;
...
$filter_8 = 256;
...
$filter_16 = 65536;
通过使用PHP,您可以轻松地将所有16个过滤器值存储在一个整数中。例如,值“257”只能使用过滤器1和过滤器8的组合来达到。如果用户选择了filter_1和filter_8,则可以通过执行以下操作来确定位掩码:

$bitmask = $filter_1 | $filter_8  //gives 257
使用表示所有过滤器状态的唯一位掩码,您也可以简单地将其用作缓存密钥,而不需要昂贵的md5操作。因此,在本例中,您需要将一个名为“257”的文件保存到缓存中

这项技术还为您提供了一个使缓存无效的简单工具,因为您可以检查新记录和更新的记录以确定它们匹配的过滤器,并删除名称中设置了该“位”的任何文件,即,
if((int)$filename)&$filter==$filter)取消链接($filename)。如果您的表有频繁的写入,这可能会导致扫描缓存时出现一些性能问题,但对于读量大的应用程序来说,这是一种不错的技术


这是我在处理位或标志时喜欢使用的方法。但是,如果你真的需要这样的缓存,你应该仔细考虑一下。如果您只有几个系统用户,那么基于几个搜索查询,您真的会遇到性能问题吗?此外,MySQL具有内置的查询缓存,在高读应用程序上性能非常好。如果您的结果页生成例程非常昂贵,那么缓存输出片段肯定是有益的,但是如果您在这里只谈论少数用户的微秒性能,那么这可能不值得。

首先验证您是否确实需要缓存(如托比建议的那样)

在那之后,想想信息需要多么新鲜——你将需要清除旧的值。您可能希望为此使用预先存在的解决方案,例如

$key = calc_key();

$result = $memcache->get($key);

if (!$result) {
  $result = get_data_from_db();
  /* cache result for 3600 seconds == 1 hour */
  $memcache->set($key, $result, 0, 3600);
}

/* use $result */