Статьи

Turbocharge Ваш сайт с Memcached

Ваш последний сайт PHP / MySQL наконец-то онлайн. И это круто. Но это не так быстро, как хотелось бы, потому что многие запросы SQL выполняются каждый раз, когда генерируется страница. И, кроме того, вы чувствуете, что он не будет хорошо масштабироваться при больших нагрузках. И вы, скорее всего, правы.

В этом уроке мы увидим, как вы можете значительно улучшить отзывчивость вашего веб-сайта и помочь масштабировать его для обработки множества одновременных посетителей, создав слой кэша между вашим кодом и вашей базой данных. Хорошей новостью является то, что это довольно легко, и может быть сделано за несколько минут!


Memcached — это высокопроизводительная система кэширования данных в памяти.

Современные веб-сайты и веб-приложения используют большое количество данных, и нередко считать за 20 или даже 30 SQL-запросов в одной генерации страницы. Умножьте эту сумму на большое количество посетителей, и вы часто получаете перегруженную базу данных и страницы, которые за считанные секунды генерируются и отправляются клиенту.

Инструмент, который мы будем использовать сегодня для повышения производительности, называется Memcached. Это высокопроизводительная система кэширования данных в памяти. Или, другими словами, очень быстрое приложение, которое запускается на вашем сервере и использует часть доступной памяти для хранения ассоциативного массива данных. Вы можете попросить Memcached сделать две вещи:

  • Сохраните значение V с помощью ключа K
  • Получить значение V сохраненное с помощью ключа K

Это выглядит минималистично, но вы можете многое сделать благодаря этим двум функциям, как мы увидим очень скоро. На самом деле Memcached может сделать еще несколько вещей, но все они связаны с хранением или извлечением данных.

Установить Memcached на современные дистрибутивы Linux довольно просто:

  • Ubuntu: sudo apt-get install memcached
  • Gentoo: sudo emerge install memcached
  • Redhat: sudo yum install memcached

После установки Memcached будет автоматически запускаться при каждой загрузке вашего сервера. Вы можете установить объем памяти, зарезервированный для Memcached, наряду с другими параметрами, в файле конфигурации ( /etc/memcached.conf ). 64Mb выделено по умолчанию. Файл конфигурации также содержит IP-адрес и порт Memcached, к которому будет привязан. Значения по умолчанию ( 127.0.0.1 и 11211 ) подходят для стандартной настройки.


Мы хотим хранить и извлекать данные из ваших PHP-скриптов. Это означает, что нам нужен способ подключения к Memcached из PHP. Для этого мы собираемся установить расширение «Memcache» для PHP. Поскольку это расширение PECL, его очень легко установить с помощью «pecl», введя следующую команду:

1
sudo pecl install memcache

Существует два расширения PHP, связанных с Memcache: «Memcache» и «Memcached» (обратите внимание на «d» во втором). Оба очень похожи, но первый имеет меньшую площадь. В этом уроке мы будем использовать более легкий Memcache . После установки это расширение должно быть включено, и теперь функции, связанные с Memcache, должны быть доступны для ваших сценариев PHP.


Наша работа здесь основана на следующих предположениях:

  • получение данных из базы данных требует ресурсов (CPU + I / O)
  • получение данных из базы данных занимает много времени
  • мы часто получаем одни и те же данные снова и снова

Мы также хотим хранить наши данные таким образом, чтобы мы могли эффективно их извлекать.

Вообще говоря, мы хотим сохранить наши данные в постоянной среде (например, в нашей базе данных MySQL). Но мы также хотим хранить наши данные таким образом, чтобы мы могли эффективно их извлекать, даже если хранилище непостоянно. В итоге у нас будет две копии наших данных : одна хранится в MySQL, а другая — в Memcache.

Вот шаги, которые мы должны предпринять, чтобы это произошло:

  • Каждая операция записи (SQL INSERTs и INSERTs ) будет выполняться как в MySQL, так и в Memcached
  • Каждая операция чтения (SQL SELECTs ) будет выполняться в Memcached и будет возвращаться к MySQL в случае ошибки

На этом этапе вы, вероятно, видите, какие части вашего кода необходимо изменить: части, в которых вы пишете данные, и части, в которых вы читаете данные. Если ваш PHP-код хорошо структурирован, вы должны были обернуть свой код доступа к данным в функции или — даже лучше — классы. Если это так, обновление вашего сайта должно быть очень быстрым. Если нет, у вас может быть немного больше работы.


Прежде всего, давайте создадим соединение с нашим сервером Memcached. Вот код, который вы должны использовать в начале своих PHP-скриптов:

1
2
3
4
5
6
7
// Connection constants
define(‘MEMCACHED_HOST’, ‘127.0.0.1’);
define(‘MEMCACHED_PORT’, ‘11211’);
 
// Connection creation
$memcache = new Memcache;
$cacheAvailable = $memcache->connect(MEMCACHED_HOST, MEMCACHED_PORT);

На данный момент мы установили соединение с нашим сервером Memcache. Возможно, это не удалось, но мы знаем это благодаря переменной $cacheAvailable .


Давайте погрузимся в хранилище данных. Мы собираемся взять пример, чтобы прояснить ситуацию — интернет-магазин. У нас есть скрипт с именем edit_product.php , цель которого — сохранить данные о продукте в нашей базе данных. Каждый из наших продуктов имеет следующую информацию:

  • Я бы
  • имя
  • описание
  • цена

В какой-то момент нашего кода edit_product.php мы выполняем SQL-запрос INSERT или UPDATE , цель которого — записать данные этого продукта в нашу базу данных MySQL. Это может выглядеть так:

1
2
3
4
5
// We have validated and sanitized our data
// We have escaped every risky char with mysql_real_escape_string()
// Now we want to save it into our database
$sql = «INSERT INTO products (id, name, description, price) VALUES ($id, ‘$name’, ‘$description’, $price)»;
$querySuccess = mysql_query($sql, $db);

Как я упоминал выше, мы хотим хранить наши данные как в нашей базе данных MySQL, так и на сервере Memcached. Вот как мы будем действовать:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
// We have validated and sanitized our data
// We have escaped every risky char with mysql_real_escape_string()
// Now we want to write them to our database :
$sql = «INSERT INTO products (id, name, description, price) VALUES ($id, ‘$name’, ‘$description’, $price)»;
$querySuccess = mysql_query($sql, $db);
 
// We have written our data into our database
// Now let’s store the product name, description and price into our cache
// The method «set» tells our Memcached server to store the data associated to a specific key
if ($querySuccess === true)
{
    // We build a unique key that we can build again later
    // We will use the word ‘product’ plus our product’s id (eg. «product_12»)
    $key = ‘product_’ .
 
    // We store an associative array containing our product data
    $product = array(‘id’ => $id, ‘name’ => $name, ‘description’ => $description, ‘price’ => $price);
 
    // And we ask Memcached to store that data
    $memcache->set($key, $product);
}

На данный момент наша база данных и кэш содержат данные о наших продуктах.


В случае, если наш кэш недоступен, мы хотим вернуться к MySQL.

Теперь давайте восстановим наши данные. В том же примере, скажем, в нашем интернет-магазине есть скрипт product.php который отображает конкретный продукт. На странице product.php?id=12 отобразится продукт с идентификатором 12.

В какой-то момент нашего кода product.php мы запускаем запрос SELECT SQL, целью которого является получение данных о продукте из нашей базы данных MySQL. Это может выглядеть так:

1
2
3
4
5
6
// We have validated and sanitized our data
// We have escaped every risky char with mysql_real_escape_string()
// Now we want to read from our database :
$sql = «SELECT id, name, description, price FROM products WHERE id = » .
$queryResource = mysql_query($sql, $db);
$product = mysql_fetch_assoc($queryResource);

Как мы уже говорили выше, мы хотим получить наши данные с нашего сервера Memcached, если это возможно, потому что это быстрее, чем получать их из MySQL. Но если наш кеш-сервер недоступен или просто не хранит нужные нам данные, мы хотим вернуться к MySQL. Вот как мы будем действовать:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Initialize our $product variable
$product = null;
 
// First we check that our cache server is available
// The $cacheAvailable variable was initialized when we connected to our cache server
if ($cacheAvailable == true)
{
    // We build the key we associated to our product data
    $key = ‘product_’ .
 
    // Now we get the data from our cache server
    $product = $memcache->get($key);
}
 
// do we need to access MySQL ?
if (!$product)
{
    // In case we do…because our $product variable is still null
    // We have validated and sanitized our data
    // We have escaped every risky char with mysql_real_escape_string()
    // Now we want to read from our database :
    $sql = «SELECT id, name, description, price FROM products WHERE id = » .
    $queryResource = mysql_query($sql, $db);
    $product = mysql_fetch_assoc($queryResource);
}

На данный момент мы получили необходимые данные. Скорее всего, это было сделано из нашего кэша, но могло быть из MySQL, если кэш не был заполнен или по какой-то причине не был доступен.


Мы видели, как Memcached можно использовать для ускорения вашего сайта и ограничения загрузки базы данных. Наш пример выше был основан на PHP и MySQL, потому что эти технологии широко распространены, но этот принцип универсален и работает точно так же со многими другими технологиями: C / C ++, Java, Python, Ruby, Perl, .Net, MySQL, Postgres, Erlang, Lua, Lisp, Cold Fusion, Ocaml и io перечислены вместе с PHP на официальной вики Memcached .

Как я кратко упомянул ранее, Memcached предоставляет больше возможностей, чем простые методы set и get, которые мы видели выше. Две полезные дополнительные функции — это увеличение / уменьшение обновлений, а также возможность задавать время истечения для определенных сохраненных данных. Оба доступны в PHP, наряду с несколькими другими, как вы можете видеть в документации Memcache .

Получайте удовольствие от внедрения этого на своих веб-сайтах и ​​наслаждайтесь улучшением производительности. Большое спасибо за чтение и, пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы в комментариях ниже.