Кэширование на стороне сервера

Уроки по PHP, Javascript и т.п.

Кэширование на стороне сервера

Сообщение Александр » 04 авг 2012, 14:20

Кэширование на стороне сервера
PHP, Cache_Lite

Изображение

В этой статье я напишу о том, как кэшировать данные на стороне сервера в файлы.
Кэширование может помочь значительно снизить нагрузку на ваш сервер, при большом количестве обращений к вашим скриптам.

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

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

В статье будет использоваться специальный класс. Он справляется с основной задачей кэширования, проверяет целостность созданного кэша и имеет дополнительные настройки. Если вам будет надо, то вы сможете написать и свой класс, когда поймёте принцип работы кэширования.



Создадим скрипт для тестирования класса для кэширования

1. Создадим базу пользователей

  1. CREATE TABLE IF NOT EXISTS `scores` (
  2.   `id` int(9) AUTO_INCREMENT,
  3.   `uid` int(9),
  4.   `score` int(10),
  5.   PRIMARY KEY  (`id`),
  6.   UNIQUE KEY `uid` (`uid`)
  7. ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
  8.  
  9. -- Наполним базу
  10. INSERT INTO `scores` (`uid`,`score`) VALUES
  11. (1,1000),
  12. (2,1300),
  13. (3,800),
  14. (4,700),
  15. (5,1500);



2. Напишем скрипт scores.php, выводящий рекорды из базы

  1. <?
  2. $db_host="localhost";   // обычно не нужно изменять
  3. $db_user="user";    // имя пользователя БД
  4. $db_password="pass";    // пароль БД
  5. $db_name = "name"// имя БД
  6.  
  7.  
  8. mysql_connect($db_host, $db_user, $db_password) or die (mysql_error());
  9. mysql_select_db($db_name) or die (mysql_error());
  10. mysql_query("SET NAMES 'utf8'");
  11.  
  12.  
  13. $query = 'SELECT * FROM `scores` ORDER BY `score` DESC LIMIT 3;';
  14. $sql = mysql_query($query);
  15.  
  16.  
  17. if (mysql_num_rows($sql)) {
  18.     while ($sql_data = mysql_fetch_array($sql)) {
  19.             echo $sql_data['uid'].' - '.$sql_data['score'].'<br />';
  20.     }
  21. }
  22.  
  23. // https://flapps.ru/forum/
  24. ?>


Можно запустить скрипт и проверить его работу.

Этот скрипт довольно простой. В нем выполняется несложный SQL запрос и нет ресурсоемких вычислений.
Для примера он подойдёт. Представьте, что вместо простого SQL запроса в этом скрипте происходит сложный SQL запрос, объединяющий несколько таблиц и сильно нагружающий сервер баз данных и, например, после выбора этих данных, в PHP происходят сложные вычисления, которые тоже сильно нагружают сервер. Либо в нашем случае, это может быть обращение к ВКонтакте API, для получения имен пользователей.

Теперь представьте, что этот скрипт будет вызван не одним пользователем, а сразу 10 пользователями одновременно в одну секунду. Или даже одновременно 1000 пользователями. Нагрузка на сервер будет очень большой.

При обращении к этому скрипту в одну и ту же секунду, пользователи получают одну и ту же информацию. Так почему бы не выполнить этот скрипт 1 раз и записать его результат в файл, а потом просто выдать всем пользователям данные из этого файла, не выполняя сложный SQL запрос и не проводя сложных вычислений? Так и нужно сделать. Это и будет кэшированием.

Если бы пользователи получали в ответ от сервера разную информацию, например которая зависимосит от их ID, то кэширование может не подойти.

При кэшировании нужно учитывать, чтобы данные были актуальными. Если кэшировать данные на 1 час, то за это время информация в кэше и в базе может стать разной.
Частоту обновления кэша нужно подбирать конкретно к вашей задаче. Нужно выбрать грань между актуальностью и нагрузкой на сервер.

Иногда кэширование имеет смысл делать даже на несколько секунд.
Если ваш проект очень сильно посещаем, например 1000 человек в секунду делают одинаковый запрос, который возвращает одинаковый результат, то можно делать кэширование на несколько секунд. Произойдёт одна ресурсозатратная операция, а остальные запросы будут взяты из кэша.

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



Применение кэширования

1. Скачиваем PHP класс Cache_Lite

Это можно сделать на странице http://pear.php.net/package/Cache_Lite/download
Нужно выбрать «For manual installation only».

В этой статье будет описана работа с последний на данный момент версией Cache_Lite 1.7.15.


2. Извлекаем папку Cache

В этой папке находятся классы, которые будут выполнять всю работу:
- Lite
-- File.php
-- Function.php
-- NestedOutput.php // необязательный файл
-- Output.php
-Lite.php

Я разархивировал эту папку в корень основной директории.


Если на вашем сервере нет PEAR, то нужно так же скачать библиотеку PEAR http://pear.php.net/package/PEAR/download
На данный момент последняя версия 1.9.4.
Из архива вытаскиваем файлы PEAR.php и PEAR5.php и кладем в папку Cache.


3. Создадим папку cache_files

В эту папку будут сохраняться файлы кэша.
Я поместил её в корень основной директории.


4. Изменим скрипт scores.php

Добавим в скрипт scores.php вывод времени выполнения скрипта

  1. // чтобы видеть в какое время скрипт был выполнен
  2. echo 'Скрипт был выполнен '.date('H:i:s').'<br />';

и код для кэширования.

Получим код:
  1. <?
  2. require_once('Cache/Lite/Output.php');
  3. $options = array(
  4.     'cacheDir' => 'cache_files/', // куда сохраняются файлы кэша
  5.     'caching' => true, // можно отключить кэширование
  6.     'lifeTime' => 5, // время жизни кэша в секундах
  7.     'writeControl'    => true, // проверка, что файл кэша был создан корректно
  8.     'readControl'     => true, // проверка файла кэша перед его выводом
  9.     'fileNameProtection' => false, // кодирование имени файла кэша
  10.     'readControlType' => 'md5' // тип контроля кэша
  11. );
  12. $cache = new Cache_Lite_Output($options);
  13.  
  14.  
  15. // начинаем кэшировать
  16. if (!($cache->start('score_page','Static'))) {
  17.     // если файл кэша данного участка существует и его время жизни ещё не прошло, то данные будут выведены из файла кэша, а следующий код не будет выполнен
  18.     // score_page - название файла кэша
  19.     // Static - группа кэша
  20.  
  21.     $db_host="localhost";   // обычно не нужно изменять
  22.     $db_user="user";    // имя пользователя БД
  23.     $db_password="pass";    // пароль БД
  24.     $db_name = "name"// имя БД
  25.      
  26.  
  27.     mysql_connect($db_host, $db_user, $db_password) or die (mysql_error());
  28.     mysql_select_db($db_name) or die (mysql_error());
  29.     mysql_query("SET NAMES 'utf8'");
  30.  
  31.  
  32.     $query = 'SELECT * FROM `scores` ORDER BY `score` DESC LIMIT 3;';
  33.     $sql = mysql_query($query);
  34.  
  35.     echo 'Скрипт был выполнен '.date('H:i:s').'<br />';
  36.     if (mysql_num_rows($sql)) {
  37.         while ($sql_data = mysql_fetch_array($sql)) {
  38.                 echo $sql_data['uid'].' - '.$sql_data['score'].'<br />';
  39.         }
  40.     }
  41.    
  42.     // заканчиваем кэширование
  43.     $cache->end();
  44. }
  45.  
  46. // https://flapps.ru/forum/
  47. ?>


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


5. Запустим скрипт

После запуска в папке cache_files появится файл cache_Static_score_page

Обновите страницу. Данные будут взяты из этого файла. В этом можно убедиться, глядя на время когда был выполнен скрипт.
Можно так же обновить данные в базе и убедится, что в кэше они не будут обновлены.
Увеличим время жизни кэша, например до 30 секунд

обновим данные в базе
  1. UPDATE scores SET score=1600 WHERE uid=1;
  2. UPDATE scores SET score=1900 WHERE uid=3;

и после этого несколько раз выполним скрипт scores.php.



Пример кэширования нескольких частей на разное время

  1. <?
  2. require_once('Cache/Lite/Output.php');
  3. $options = array(
  4.     'cacheDir' => 'cache_files/', // куда сохраняются файлы кэша
  5.     'caching' => true, // можно отключить кэширование
  6.     'lifeTime' => 5, // время жизни кэша в секундах
  7.     'writeControl'    => true, // проверка, что файл кэша был создан корректно
  8.     'readControl'     => true, // проверка файла кэша перед его выводом
  9.     'fileNameProtection' => false, // кодирование имени файла кэша
  10.     'readControlType' => 'md5' // тип контроля кэша
  11. );
  12. $cache = new Cache_Lite_Output($options);
  13.  
  14.  
  15. // начинаем кэшировать
  16. // время жизни кэша берется из настроек выше
  17. if (!($cache->start('page_part_1','Static'))) {
  18.     echo 'Первый участок кода был выполнен '.date('H:i:s').'<br />';
  19.     $cache->end();
  20. }
  21.  
  22. // поменяем время жизни кэша
  23. $cache->setLifeTime(15);
  24. if (!($cache->start('page_part_2','Static'))) {
  25.     echo 'Второй участок кода был выполнен '.date('H:i:s').'<br />';
  26.     $cache->end();
  27. }
  28.  
  29. // https://flapps.ru/forum/
  30. ?>



Очистка кэша

Очистить кэш можно просто удалив файлы кэша из папки cache_files либо с помощью php скрипта.

Для удаления файла кэша можно использовать

Необходимо указать имя кэша и группу.

Либо

Удалит все файлы кэша группы Static.


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

Эта статья не раскрывает полного функционала класса Cache_Lite.

Скачать файлы из этой статьи Чтобы увидеть ссылку - зарегистрируйтесь


Например, если нужно закэшировать только одно строковое значение переменной:
  1. <?
  2. require_once('Cache/Lite/Output.php');
  3. $options = array(
  4.     'cacheDir' => 'cache_files/', // куда сохраняются файлы кэша
  5.     'caching' => true, // можно отключить кэширование
  6.     'lifeTime' => 5, // время жизни кэша в секундах
  7.     'writeControl'    => true, // проверка, что файл кэша был создан корректно
  8.     'readControl'     => true, // проверка файла кэша перед его выводом
  9.     'fileNameProtection' => false, // кодирование имени файла кэша
  10.     'readControlType' => 'md5' // тип контроля кэша
  11. );
  12. $cache = new Cache_Lite_Output($options);
  13.  
  14. if ($data = $cache->get('value1')) {
  15.     echo $data;
  16. } else {
  17.     $data = 'Data of the value1';
  18.     $cache->save($data);
  19. }
  20.  
  21. // https://flapps.ru/forum/
  22. ?>

За это сообщение автора Александр поблагодарили - 3:
Abdul-Ibn-Abusheih, Alazaur, gpv123
Аватара пользователя
Александр
Создатель сайта
Создатель сайта
 
Автор темы
Сообщения: 4574
Зарегистрирован: 27 сен 2009, 16:45
Откуда: Санкт-Петербург
Благодарил (а): 126 раз.
Поблагодарили: 771 раз.

Чтобы убрать блок с рекламой, зарегистрируйтесь на форуме или войдите.

Google
 



Re: Кэширование на стороне сервера

Сообщение Alazaur » 04 авг 2012, 14:51

Вот это труд :shock:

За это сообщение автора Alazaur поблагодарил:
gpv123
Alazaur
Разработчик
Разработчик
 
Сообщения: 1001
Зарегистрирован: 16 окт 2011, 20:25
Благодарил (а): 24 раз.
Поблагодарили: 121 раз.


Вернуться в Уроки на другие темы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0