我正在使用一个搜索应用程序,该应用程序使用一个包含16个过滤器选项的表单,这些选项可以是1(选中)或0(未选中)。使用GET请求通过AJAX检索JSON的结果。
查询字符串如下所示:
filter_1 = 0& filter_2 = 1 ...省略...& filter_16 = 1& page = 20
每个搜索结果至少有2个页面可由用户浏览。
我的问题是:如何根据输入参数缓存搜索结果?我的第一个想法是md5请求参数,然后使用hash作为文件名写一个缓存文件。
每次有新请求进入时,我都会搜索缓存文件,如果存在,则使用该文件中的数据,而不是查询数据库并将行转换为json结果。
但由于有许多搜索选项,这似乎不是一个好主意。会有很多缓存文件(16 * 16 ???),并且由于应用程序仅供少数用户使用,我怀疑所有可能的组合都会被缓存。每个结果都包含X页,因此每个页面都是自己的缓存文件(16 * 16 * X)。
这样的应用程序有什么好的缓存策略?实际上是否可以实现缓存?
答案 0 :(得分:1)
为什么需要缓存?
如果应用程序仅由少数用户使用,则实际上可能不需要缓存。
答案 1 :(得分:1)
因为所有搜索参数都是0或1的标志,所以您可能会考虑使用位掩码。
每个过滤器都代表一个2的幂:
$filter_1 = 1;
$filter_2 = 2;
$filter_3 = 4;
...
$filter_8 = 256;
...
$filter_16 = 65536;
通过使用PHP的bitwise operators,您可以轻松地将所有16个过滤器值存储在一个整数中。例如,只能使用filter_1和filter_8的组合来达到值“257”。如果用户选择了filter_1和filter_8,则可以通过执行以下操作来确定位掩码:
$bitmask = $filter_1 | $filter_8 //gives 257
使用唯一的位掩码表示所有过滤器的状态,您也可以将其用作缓存键,而无需昂贵的md5操作。因此,在这种情况下,您可以将名为“257”的文件保存到缓存中。
这种技术为您提供了一个简单的工具来使您的缓存无效,因为您可以检查新的和更新的记录以确定它们匹配的过滤器,并删除名称中设置了“位”的任何文件,即。 if ( ((int)$filename) & $filter == $filter) unlink($filename);
。如果您的表经常写入,这可能会导致扫描缓存时出现一些性能问题,但对于读取繁重的应用程序来说,这是一种不错的技术。
这是我喜欢在处理位或标志时使用的方法。如果你真的需要像这样的缓存,你应该仔细考虑。如果您只有少量系统用户,您是否真的会遇到基于少量搜索查询的性能问题?同样,MySQL具有内置的查询缓存,在高读取应用程序上运行良好。如果你的结果页面生成例程很昂贵,那么缓存输出片段肯定是有益的,但如果你只是为少数几个用户谈论微秒的性能,那么它可能是不值得的。
答案 2 :(得分:0)
鉴于您描述的要求(少量用户),在我看来,缓存所有组合似乎是合理的。当然,除非缓存有意义。典型查询需要多长时间?既然你说应用程序只会被几个人使用,那么它是否值得缓存?我非常粗略的估计是,如果在这种情况下查询不需要几秒钟,请不要担心缓存。如果它不到一秒钟,并且您真的不想让应用程序具有超级响应性,则不需要缓存。
否则,我会说(再次给予少量用户)缓存所有组合都可以。即使使用了大量的数据,它们仍然最多有65536个,许多现代操作系统可以轻松处理目录中的数千个文件(如果您计划缓存到文件中)。但无论如何,限制缓存中的项目数量并定期清除旧项目是合理的。另外,我不会使用MD5,我只会将过滤器中的0和1连接到缓存键(例如0101100010010100)。
答案 3 :(得分:0)
首先确认您确实需要缓存(如Toby建议的那样)。
在那之后,想想信息需要多么新鲜 - 你需要清除旧的价值观。您可能希望使用预先存在的解决方案,例如memcached。
$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 */