当我们想到网络应用程序中的存储时,我们首先想到的通常是像 MySQL 这样的传统数据库。这非常适合长期存储和数据分析,但对于许多短期需求,还有一个更好的选择:memcached。这是在页面请求之间保存信息位和提高性能的绝佳选择。在本简介中,我们将向您展示如何开始将 memcached 与 PHP 结合使用。
简介
Memcached 只是一个带有接口的服务器,可让您将内容存储在内存中。这可以与您的 Web 服务器在同一台机器上运行,但可扩展性来自于跨多个服务器分布实例。您所需要的只是运行的 memcached 守护进程,PHP 提供了一个带有 PECL 库的简单接口。在基于 Debian 的 Linux 系统上,这非常简单:
$ sudo apt-get install memcached $ sudo service memcached start $ sudo pecl install memcached $ sudo service httpd restart
现在我们应该提到技术上有两个 PHP 库可用于 memcached。较旧的库称为“memcache”,缺少某些功能。较新的“memcached”库使用 libmemcached,通常是首选。
PHP 的第一步是连接到服务器。连接可以跨请求保持,这对性能有好处。然后根据需要添加到服务器列表。在这种情况下,我们将在默认端口上使用本地运行的实例:
function get_memcached() { // Set a persistent connection ID $mc = new Memcached('webapp'); // Set a short timeout (in milliseconds) so if the server goes down // it doesn't take down our site with it $mc->setOption(Memcached::OPT_CONNECT_TIMEOUT, 1000); if ( !$mc->getServerList() ) { if ( !$mc->addServer('localhost', 11211) ) { error_log('Could not add memcached server.'); return false; } } return $mc; }
现在您可以使用基于您定义的键的简单函数读取 PHP 变量并将其写入 memcached。它们将被自动序列化和反序列化。您不能编写数据库连接或结果集等资源,但您可以将这些结果集转换为数组并存储它们。
$mc->set('list', array(1, 2, 3)); $list = $mc->get('list');
存储数据
假设我们要为每个登录用户存储最近访问过的 URL 列表。我们可以使用会话,但这不能跨设备工作,一旦会话被清除,它就会消失。我们可以使用数据库,但对于这种很可能对我们的系统不重要的数据来说速度很慢。使用 memcached 这很容易:
$user_id = 123; // The current user's ID $recents = array(); if ($mc = get_memcached()) { // Get any stored in memcached $recents = $mc->get("recents-$user_id"); if (!$recents) { $recents = array(); } $recents[] = $_SERVER['REQUEST_URI']; $recents = array_unique($recents); $mc->set("recents-$user_id", $recents); } print_r($recents);
缓存
现在让我们通过缓存数据库结果来真正提升您的 Web 应用程序。数据库查询通常是服务器处理中的最大瓶颈,因此通过在内存中缓存结果来避免重复查询可以提供巨大的性能提升。最简单的方法是只用主键查询和存储。通常,最好在更新数据库记录时删除缓存的值,这样用户永远不会看到任何过时的值。
function store_product($id, $name, $price) { // Create or update the product in the database $db = get_db(); $qry = $db->prepare('REPLACE INTO product (id, name, price) VALUES (:id, :name, :price)'); $qry->bindParam(':id', $id); $qry->bindParam(':name', $name); $qry->bindParam(':price', $price); $qry->execute(); // Remove outdated values from cache if it's there if ($mc = get_memcached()) { $mc->delete("product-$id"); } } function get_product($id) { $product = null; // First check the cache if ($mc = get_memcached()) { $product = $mc->get("product-$id"); } if (!$product) { // Not in the cache; check the db $qry = $db->prepare('SELECT * FROM product WHERE id = $id'); $qry->bindParam(':id', $id); if ($qry->execute()) { $product = $qry->fetch(); // Cache for future use if ($mc) { $mc->set("product-$id", $product); } } } return $product; }
注意事项
与任何技术选择一样,存在局限性和需要注意的事项:
- 密钥的最大长度为 250 字节。保持您的密钥简单和简短。
- 默认的最大值大小约为 1MB。这不是存储大值的正确位置。
- 存储不会像锁定数据库记录那样锁定读取或写入。请注意,任何 Web 请求都可以随时更新任何值。
- 确保您的 memcached 服务器有足够的组合 RAM。
后续步骤
您可以使用 memcached 做更多的事情:
- 缓存的值可以有超时。当数据应该缓存一段时间而不是手动删除时,这很有用。
- 简单的
increment
和decrement
方法有助于保持快速请求之间的计数器。 - 正确配置 memcached 后,您可以在使用多种编程语言编写的应用程序之间共享数据。
试试 memcached。在适当的情况下,这是一种非常简单有效的解决方案,可以最大限度地提高您的网络应用程序的性能。