介绍
随着您的网站增长,流量增加,显示压力最快的组件之一是后端数据库。 如果您的数据库没有分布和配置为处理高负载,它可能很容易被流量相对适度增加所淹没。
处理这个问题的方法之一是利用一个内存对象缓存系统,如memcached的 。 Memcached是一个缓存系统,通过临时存储信息在内存中工作,通常从数据库中检索。 对内存中信息的下一个请求是非常快的,而不会对后端数据库造成压力。
在本指南中,我们将讨论如何在Ubuntu 14.04服务器上安装和使用memcached。
先决条件
在我们开始之前,你应该有你的服务器上谁有权访问到正规,非root用户sudo
权限。 如果您尚未创建这样的用户,可以通过以下第1步-4在我们这样做初始设置指南的Ubuntu 14.04 。
配置常规用户后,请继续执行本指南。
安装Memcached和组件
要开始,我们应该从Ubuntu的存储库获取我们需要的所有组件。 幸运的是,我们需要的一切都是可用的。
由于这是我们与第一次手术apt
在这个环节,我们要更新我们的本地包索引。 然后我们可以安装我们的程序。
我们将安装memcached以及MySQL数据库后端和PHP来处理交互。 我们还安装了处理memcached交互的PHP扩展。 您可以通过键入以下内容获得所需的一切:
sudo apt-get update
sudo apt-get install mysql-server php5-mysql php5 php5-memcached memcached
请注意,有*两个“可用的PHP的memcache扩展。一个叫php5-memcache
,另一个被称为php5-memcached
(注意尾随”在第二个例子D“)。我们在使用这些第二,因为它是稳定的并实现更广泛的功能。
如果您尚未安装MySQL,安装将提示您选择并确认管理员的密码。
这应该安装和配置你需要的一切。
检查安装
相信不知道,memcached已经完全安装并准备好了。 我们可以用很多不同的方法来测试。
第一种方法相当简单。 我们可以问PHP是否知道我们的memcached扩展,以及它是否被启用。 我们可以通过创建无处不在的PHP信息页来做到这一点。
这是很容易通过创建一个名为完成info.php
在我们的文档根目录。 在Apache中在Ubuntu 14.04,我们的默认文档根目录是/var/www/html
。 使用root权限打开文件:
sudo nano /var/www/html/info.php
在此文件中,键入。 这基本上只是调用一个PHP函数,收集和打印我们的服务器的信息到一个网页友好的布局。
<?php
phpinfo();
?>
现在,您可以访问您的服务器的域名或公网IP地址后面/info.php
,你应该看到的信息页面。
http://server_domain_name_or_IP/info.php
如果向下滚动或搜索“memcached”节标题,则应该找到如下所示的内容:
这意味着memcached扩展被启用,并被web服务器找到。
我们还可以通过键入以下内容检查memcached服务是否正在运行:
ps aux | grep memcached
memcache 6584 0.0 0.0 327448 3004 ? Sl 14:07 0:00 /usr/bin/memcached -m 64 -p 11211 -u memcache -l 127.0.0.1
demouser 6636 0.0 0.0 11744 904 pts/0 S+ 14:29 0:00 grep --color=auto memcached
您可以通过键入以下内容来查询统计信息的服务:
echo "stats settings" | nc localhost 11211
如果您需要停止,启动或重新启动memcached服务,可以通过键入以下内容来完成:
sudo service memcached restart
测试Memcached是否可以缓存数据
现在我们已经验证memcached正在运行,并且我们的PHP扩展与其连接已启用,我们可以尝试让它存储数据。
我们将通过创建另一个PHP脚本来做到这一点。 这一次,它会更复杂。
打开一个名为cache_test.php
在我们的文档根目录:
sudo nano /var/www/html/cache_test.php
在内部,首先创建PHP包装器标签:
<?php ?>
其中,我们将创建一个PHP Memcached对象的新实例,并将其存储在一个变量中。 我们要定义这个PHP对象可以连接到我们服务器上运行的实际memcached服务的位置。 Memcached的端口上运行11211
默认:
<?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); ?>
接下来,我们要告诉Memcached实例从缓存中查询一个键。 这个键可以被称为任何东西,因为我们还没有创建它。 我们将使用“blah”。 该请求的结果将被存储到$result
变量:
<?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); $result = $mem->get("blah"); ?>
接下来,我们只需要测试是否返回了任何内容。 如果memcached找到一个名为“blah”的键,我们希望它打印与该键相关联的值。 如果memcached无法找到匹配的键,我们应该打印一条消息说。
然后我们应该设置一个值为key,这样下次我们要求的值,memcached会找到我们给它的值:
<?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); $result = $mem->get("blah"); if ($result) { echo $result; } else { echo "No matching key found. I'll add that now!"; $mem->set("blah", "I am data! I am held in memcached!") or die("Couldn't save anything to memcached..."); } ?>
在这一点上,我们的脚本完成了。 如果我们在我们的网络浏览器访问此网页,我们可以看到这是如何工作:
http://server_domain_name_or_IP/cache_test.php
您最初应该看到如下所示的页面:
但是,如果我们刷新页面,我们应该看到一个不同的消息:
如您所见,我们的memcached服务现在缓存了我们脚本设置的数据。
测试临时缓存数据库值
现在我们已经测试了我们在memcached中存储数据的能力,我们可以展示一个更现实的场景:从数据库查询中临时缓存结果。
在MySQL中创建示例数据
为此,我们首先需要在我们的数据库中存储一些信息。
通过键入this连接到您的MySQL实例作为管理用户。 您必须输入在安装期间设置的MySQL root密码:
mysql -u root -p
然后,您将获得一个MySQL提示符。
首先,我们要创建一个数据库进行测试。 然后我们选择数据库:
CREATE DATABASE mem_test;
USE mem_test;
让我们创建一个名为用户test
使用密码testing123
能够访问我们创建的数据库:
GRANT ALL ON mem_test.* TO test@localhost IDENTIFIED BY 'testing123';
现在,我们将创建一个真正基本的表,并在其中插入一条记录。 该表将被称为sample_data
,它只是有一个索引和一个字符串字段:
CREATE TABLE sample_data (id int, name varchar(30));
INSERT INTO sample_data VALUES (1, "some_data");
现在,我们已经创建了结构并插入了数据。 我们可以退出MySQL:
exit
创建PHP脚本以缓存MySQL数据
现在我们有了MySQL中的数据,我们可以创建另一个PHP脚本,它将以类似于生产PHP应用程序的方式运行。
它将查找memcached中的数据,并在找到数据时返回。 如果它没有找到数据,它将从数据库本身进行查询,然后将结果存储在memcached中以备将来查询。
首先,在我们的文档根目录中创建另一个PHP脚本。 我们称这个脚本database_test.php
:
sudo nano /var/www/html/database_test.php
以类似于我们上一个脚本的方式开始。 我们将创建一个PHP memcached实例,然后告诉它在我们的服务器上运行的memcached服务所在的位置,就像我们上次所做的那样:
<?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); ?>
接下来,在我们第一次离开我们的上一个脚本时,我们将要定义PHP如何连接到我们的MySQL数据库。 我们需要为我们创建的用户指定登录凭据,然后我们需要告诉它要使用哪个数据库:
<?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); mysql_connect("localhost", "test", "testing123") or die(mysql_error()); mysql_select_db("mem_test") or die(mysql_error()); ?>
接下来,我们将要设计查询,我们需要获取我们插入到表中的数据。 我们将在存储到$query
变量。
然后,我们将创建一个$querykey
变量来存储memcached的将使用引用我们的信息的关键。
我们使用字符串“KEY”创建这个键,然后将我们的查询的md5(一个哈希方法)校验和附加到结尾。 这将确保每个键是唯一的,如果我们在更大的数据集上使用这种技术。 它还确保匹配查询将为后续请求生成相同的密钥。
<?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); mysql_connect("localhost", "test", "testing123") or die(mysql_error()); mysql_select_db("mem_test") or die(mysql_error()); $query = "SELECT ID FROM sample_data WHERE name = 'some_data'"; $querykey = "KEY" . md5($query); ?>
接下来,我们将创建一个$result
变量,就像我们的最后一个脚本。 这将保持我们的memcached查询的结果,就像以前一样。 我们要求memcached查询我们生成的查询关键字,看看它是否有一个由系统中该键标识的记录。
<?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); mysql_connect("localhost", "test", "testing123") or die(mysql_error()); mysql_select_db("mem_test") or die(mysql_error()); $query = "SELECT name FROM sample_data WHERE id = 1"; $querykey = "KEY" . md5($query); $result = $mem->get($querykey); ?>
我们现在准备做实际的测试逻辑,它将确定在memcached中找到结果时会发生什么。 如果找到结果,我们要打印我们拉出的数据,并告诉用户我们可以直接从memcached中检索它:
<?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); mysql_connect("localhost", "test", "testing123") or die(mysql_error()); mysql_select_db("mem_test") or die(mysql_error()); $query = "SELECT name FROM sample_data WHERE id = 1"; $querykey = "KEY" . md5($query); $result = $mem->get($querykey); if ($result) { print "<p>Data was: " . $result[0] . "</p>"; print "<p>Caching success!</p><p>Retrieved data from memcached!</p>"; } ?>
现在,让我们为替代场景添加逻辑。 如果没有找到结果,我们希望使用我们制作的要求为MySQL的数据查询。 我们将这种存储到$result
我们做了变量。 这将是一个数组的形式。
在我们得到查询的结果之后,我们需要将该结果添加到memcached中,以便下次我们这样做时数据就会存在。 我们可以通过喂食memcached的,我们想用引用数据的密钥做到这一点(我们已经与创建此$querykey
变量),数据本身(存储在$result
从MySQL查询变量)和时间以秒为单位缓存数据。
我们将缓存我们的内容10秒钟。 在现实世界中,最有可能更快地缓存内容。 也许更接近10分钟(600秒)如果你的内容没有太大变化。 对于测试,较小的值可以让我们更快地看到发生了什么,而无需重新启动memcached服务。
然后,我们将打印一个类似的消息与查询结果,并告诉用户发生了什么。 我们要这整个区块添加为else
我们以前if
:
<?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); mysql_connect("localhost", "test", "testing123") or die(mysql_error()); mysql_select_db("mem_test") or die(mysql_error()); $query = "SELECT name FROM sample_data WHERE id = 1"; $querykey = "KEY" . md5($query); $result = $mem->get($querykey); if ($result) { print "<p>Data was: " . $result[0] . "</p>"; print "<p>Caching success!</p><p>Retrieved data from memcached!</p>"; } else { $result = mysql_fetch_array(mysql_query($query)) or die(mysql_error()); $mem->set($querykey, $result, 10); print "<p>Data was: " . $result[0] . "</p>"; print "<p>Data not found in memcached.</p><p>Data retrieved from MySQL and stored in memcached for next time.</p>"; } ?>
这是我们完成的脚本。 它将尝试从memcached获取数据并返回它。 如果没有,它将直接从MySQL查询并缓存结果10秒钟。
测试脚本
现在我们已经编写了脚本,我们可以通过在我们的Web浏览器中转到我们的文件位置来运行它:
http://server_domain_name_or_IP/database_test.php
第一次访问页面时,我们应该看到如下所示的输出:
如果我们刷新(在我们上次访问的10秒内),该页面现在应显示不同的消息:
如果我们再次等待,缓存的内容将过期,并再次从memcached中删除。 我们可以在此时刷新以再次获取第一条消息,因为服务器必须返回到数据库以获取适当的值。
结论
到目前为止,您应该对memcached的工作原理有一个正确的了解,以及如何利用它来防止您的Web服务器针对相同的内容重复访问数据库。
虽然我们在本指南中创建的PHP脚本只是示例,他们应该给你一个好主意如何系统工作。 它还应该给你一个好主意,如何构建你的代码,以便你可以检查memcached并回退到数据库,如果必要的话。