Redis 加速现有应用:缓存查询,减轻服务器负载
核心要点:
我们之前已经介绍过 PHP 中 Redis 的基础知识,但现在是时候介绍一个实际应用案例了。在本教程中,我们将它添加到已部署的应用程序中,以提高应用程序速度。
您可以克隆应用程序的 0.6 版本来轻松学习。
问题描述:
在应用解决方案之前,我们需要明确问题定义。
所讨论的应用程序在执行查询时,会访问 Diffbot 的 API 并查询数据集。然后返回并显示子集。这可能需要 5 秒左右的时间,具体取决于 Diffbot 服务器的繁忙程度。虽然随着他们扩展计算能力,这种情况无疑会得到改善,但如果可以记住并重复使用一次执行的查询结果 24 小时,那就太好了,因为集合本身也只有这么频繁的更新。
您可能会想:“缓存单个查询有什么好处?” 大多数人不会经常搜索相同的内容。
事实上,研究表明,人们经常搜索相同的内容(React 流行?“react”查询突然增加),他们也会非常可靠地搜索知名作者(或他们自己)。考虑到实现此缓存几乎不花任何成本(实际上通过减少服务器压力来降低成本),添加它是一个简单的胜利,即使它不像希望的那样频繁使用。 没有理由不添加它——它 只能对我们有利。
在明确定义问题后,让我们处理先决条件。
安装:
首先,我们需要将 Redis 安装到开发和生产环境中(请注意,如果您在本地开发中使用 Homestead,则 Redis 已经安装,但在撰写本文时版本为 3.0.1)。
我们可以通过操作系统的包管理器来完成此操作:
<code class="language-bash">sudo apt-get install redis-server</code>
这是最简单也是推荐的方法,但我们也可以从头开始安装并手动配置它。根据其网站上的说明,可以通过以下方式完成:
<code class="language-bash">sudo apt-get install gcc make build-essential tcl wget http://download.redis.io/releases/redis-3.0.2.tar.gz tar xzf redis-3.0.2.tar.gz cd redis-3.0.2 make make test sudo make install</code>
如果您在运行 make 后遇到提及 jemalloc.h 的致命错误,只需运行 make distclean,然后再次运行 make。make test 命令是可选的,但很有帮助。
注意:如果您正在阅读本文并且版本 3.0.2 已不再是最新的,只需将命令调整为最新的版本号。
为了防止一些常见的警告(至少在 Ubuntu 上),我们还预防性地运行以下命令:
<code class="language-bash">sudo sh -c 'echo "vm.overcommit_memory=1" >> /etc/sysctl.conf' sudo sh -c 'echo "net.core.somaxconn=65535" >> /etc/sysctl.conf' sudo sh -c 'echo "never" > /sys/kernel/mm/transparent_hugepage/enabled'</code>
我们还确保将最后一个命令添加到 /etc/rc.local,位于 exit 0 的正上方,以便在每次服务器重启时重新执行它。最后,我们可以使用 sudo reboot 重启服务器,并通过运行 sudo redis-server 来检查 Redis 是否正常运行。
最后,我们需要确保 Redis 在服务器重启后自动启动,因此我们将按照官方说明完成此操作。
Predis:
我们之前已经介绍过 Predis 的基础知识,在本例中我们也将使用它。让我们使用以下命令安装它:
<code class="language-bash">composer require predis/predis</code>
接下来,假设我们已经掌握了前面提到的 Predis 入门知识。
自从那篇文章发表以来,引入了一些细微的差别(例如向命名空间的过渡),但我们需要使用的 API 大致相同。
实现:
为了在我们的应用程序中使用 Redis,我们需要遵循以下步骤:
因此,实现非常简单:在“表单提交”检查(查找“search”参数的那个检查)下,我们实例化 Predis 客户端,计算执行的搜索查询的 md5 哈希值,然后检查其结果是否已缓存。如果为假,则之前的流程继续,只是不会以:
<code class="language-php">$result = ... $info = ...</code>
结束,而是直接将结果序列化并保存到缓存中。然后,在代码块的外部,我们从缓存中获取结果,应用程序的流程照常继续。因此,index.php 文件中更改的部分如下所示:
<code class="language-php">// 检查是否提交了搜索表单 if (isset($queryParams['search'])) { $redis = new Client(); $hash = md5($_SERVER['QUERY_STRING']); if (!$redis->get($hash . '-results')) { $diffbot = new Diffbot(DIFFBOT_TOKEN); // 构建搜索字符串 $searchHelper = new SearchHelper(); $string = (isset($queryParams['q']) && !empty($queryParams['q'])) ? $queryParams['q'] : $searchHelper->stringFromParams($queryParams); // 基础设置 $search = $diffbot ->search($string) ->setCol('sp_search') ->setStart(($queryParams['page'] - 1) * $resultsPerPage) ->setNum($resultsPerPage); $redis->set($hash . '-results', serialize($search->call())); $redis->expire($hash . '-results', 86400); $redis->set($hash . '-info', serialize($search->call(true))); $redis->expire($hash . '-info', 86400); } $results = unserialize($redis->get($hash . '-results')); $info = unserialize($redis->get($hash . '-info')); }</code>
测试后,我们可以看到它运行良好——如果我们刷新页面或执行另一个查询然后返回到之前的查询,则一次执行的查询是即时的。最后,我们可以添加、提交和推送以进行部署:
<code class="language-bash">git add -A git commit -m "Added Redis cache [deploy:production]" git push origin master</code>
就是这样!我们的应用程序的最新版本现已上线,Redis 正在提供缓存的数据。
注意:如果您想知道我们如何通过单个提交从开发模式切换到生产部署,您应该阅读这篇文章。
微调:
为了进一步提高性能,Predis 建议安装 phpiredis,这是一个 PHP 扩展,用于“降低 Redis 协议序列化和解析的开销”。既然我们完全控制服务器,为什么不这样做呢?
<code class="language-bash">sudo apt-get install redis-server</code>
这安装了先决条件并启用了扩展。现在我们要做的就是配置 Predis 客户端以使用 phpiredis 连接。我们需要替换:
<code class="language-bash">sudo apt-get install gcc make build-essential tcl wget http://download.redis.io/releases/redis-3.0.2.tar.gz tar xzf redis-3.0.2.tar.gz cd redis-3.0.2 make make test sudo make install</code>
为:
<code class="language-bash">sudo sh -c 'echo "vm.overcommit_memory=1" >> /etc/sysctl.conf' sudo sh -c 'echo "net.core.somaxconn=65535" >> /etc/sysctl.conf' sudo sh -c 'echo "never" > /sys/kernel/mm/transparent_hugepage/enabled'</code>
就是这样!我们的 Redis 安装现在更快了!
结论:
在本教程中,我们结合使用 Redis 和 Predis 库,使已部署的应用程序看起来速度更快。我们利用 DigitalOcean droplet 的可用 RAM 来每天保存一次查询的结果,然后从缓存中返回这些结果,而不是进行往返于其来源的传输。这意味着结果并不总是最新的,但根据这篇文章,结果本身也不比这更频繁地更新。
希望本教程向您展示了向应用程序添加内存缓存层是多么简单,并且当您需要缩短加载时间并降低服务器成本时,它将非常有用。
有任何其他建议?技巧?评论?请在下面留言!
(此处省略了FAQ部分,因为FAQ部分内容与文章主体内容重复,属于冗余信息。伪原创应避免重复内容。)
以上是使用REDIS缓存加速现有应用程序的详细内容。更多信息请关注PHP中文网其他相关文章!