我有很多用户在 apache 服务器上轮询我的 php 脚本,他们运行的 mysql 查询是
"SELECT * FROM `table` WHERE `id`>'example number'
示例编号可能因用户而异,但有一个已知的下限,每 10 分钟更新一次。
每个用户每秒都会轮询服务器两次。
可以使用memcache吗?向用户显示最新信息并不重要,如果它落后一秒左右就可以了。
该站点在高峰时段有 200 个并发用户。它非常低效并且耗费大量资源。
为了给出准确的答案,我需要更多信息
查看您构建问题的方式,用户似乎没有在轮询任何个性化信息。所以我假设“示例编号”也作为轮询请求的一部分出现。
我同意@roberttstephens 和@Filippos Karapetis,您可以使用理想的解决方案
但是,由于你们已经在野外使用了该应用程序,因此实施上述解决方案将产生成本,因此这些是我推荐的实用解决方案。
使用反向代理——例如:varnish。[假设“示例编号”是请求的一部分]
如果“示例编号”不是请求的一部分,并且您必须从数据库中获取它[通过查看用户表可能是..]然后@roberttstephens 方法是要走的路。只是为了给你确切的图片,我已经重构了一点代码。`addServer('localhost', 11211);
$inputNumber = 12345;
$cacheKey = "poll:".$inputNumber;
$result = $m->get($cacheKey);
if ($result) {
return unserialize($result);
}
$sth = $dbh->prepare("SELECT column1, column2 FROM poll WHERE id = $inputNumber");
$sth->execute();
$poll_results = $sth->fetch(PDO::FETCH_OBJ);
$m->set($cacheKey, serialize($poll_results));`
在我看来,您在这里尝试使用错误的工具来完成这项工作。
memcached 是一个键/值存储,因此您可以使用给定的一组键快速存储和检索多个值。但是,您似乎事先并不知道您想要的键,因为您正在查找 id 大于数字的所有记录,而不是 ID 的集合。因此,在我看来,memcached 不适合在您的场景中使用。
以下是您的选择:
如果您正确调整 MySQL,它会非常快。你可以:
为每个表添加适当的索引
使用准备好的语句,这可以帮助您提高性能,因为用户使用不同的参数一遍又一遍地执行相同的查询
使用查询缓存
这是一个包含一些关于 MySQL 调优的提示的指南,以及mysqltuner,一个 Perl 脚本,可以指导您完成优化 MySQL 数据库所需的选项。
有 memcached 的替代品,最著名的是redis。redis 确实允许更大的灵活性,但它比 memcached 更复杂。对于您的场景,您可以使用 redis zrange命令来检索您想要的结果 - 查看可用的redis 命令以获取更多信息。
您可以使用文档存储NoSQL数据库,最著名的例子是MongoDB。
您可以在 MongoDB 中使用比在 memcached 中更复杂的查询(例如,使用运算符,如您需要的“大于”)。这是一个如何使用运算符搜索 mongo 集合中的结果的示例(检查示例 2)。
查看PHP MongoDB手册以获取更多信息。
此外,这个 SO question是关于文档存储 NoSQL 数据库的有趣读物。
您绝对可以使用 memcached 来缓存结果。相反,您可以在 mysql 中轻松创建缓存表。
无论哪种情况,您都需要为缓存创建一个 id,并根据该 id 检索结果。您可以使用 entity_name:entity_id 或 namespace:entity_name:entity_id 之类的东西,或者任何适合您的东西。
请记住,memcached 是服务器上运行的另一项服务。您必须安装它,将其设置为在重新启动时启动(或者至少应该),分配内存等。您还需要 php-memcached。
话虽如此,请查看 memcached 上的 php 文档。http://php.net/manual/en/memcached.set.php。假设您的投票 id 是 12345,您可以像这样使用 memcached。
<?php
// Get your results however you normally would.
$sth = $dbh->prepare("SELECT column1, column2 FROM poll WHERE id = 12345");
$sth->execute();
$poll_results = $sth->fetch(PDO::FETCH_OBJ);
// Set up memcached. It should obviously be installed, configured, and running by now.
$m = new Memcached();
$m->addServer('localhost', 11211);
$m->set('poll:12345', serialize($poll_results));
这个例子没有任何错误检查或任何东西,但这应该解释如何去做。我现在也没有运行 php、mysql 或 memcached 实例,因此上述内容尚未经过测试。