Кеширане и memcached. Използване на memcached в php phpMemcachedAdmin - мониторинг, статистика и управление на Memcached

В интернет има много информация по тази тема, но въпреки това мнозина я избягват. Целта на тази публикация е да обясни с един поглед основите на взаимодействието с Memcached.

Какво е Memcache и какво общо има с PHP?

Memcache е проектиран да кешира данни, които изискват много ресурси за генериране. Този тип данни могат да съдържат всичко - от резултатите от заявка към база данни до тежка част от шаблон. Memcached не е включен в основния набор от модули, които идват с PHP, но е наличен в хранилището на pecl.

Монтаж и конфигурация

Реших да използвам Debian като разглежданата дистрибуция, защото най-често се използва при създаване на уеб сървъри. Модулът Memcached за PHP е наличен във вече компилираното хранилище (php5-memcached), но ще опиша процеса на инсталиране от изходния код, тъй като не всички хранилища са толкова богати, колкото това на Debian.

Инсталиране на сървъра Memcached

#apt-get install memcached
Като начало, следната конфигурация ще ви бъде достатъчна:
#/etc/memcached.conf
#Memcached ще работи като демон

#Дневникът ще бъде добавен там
лог файл /var/log/
#Ние ще разпределим 256 мегабайта RAM за съхранение
-m 256
#Този порт ще слуша
-стр. 11211
#По-късно е препоръчително да се промени
- ти никой
#Слушайте localhost
-l 127.0.0.1

#/etc/init.d/memcached рестартиране
Проверка
# netstat -tap | grep memcached
tcp 0 0 localhost:11211 * :* СЛУШАЙТЕ 13036 /

Компилирайте и инсталирайте модула за PHP

apt-get инсталирайте php5-dev libmemcache-dev

Pecl изтеглете memcache
tar xzvf memcache-2.2.6.tgz
cd memcache-2.2.6/
phpize && ./ configure --enable-memcache && make
cp модули/ / usr/ lib/ php5/ 20060613 /

echo "разширение=memcache.so" >> / etc/ php5/ apache2/ php.ini
/etc/init.d/apache2 рестартирайте


Това е всичко! Изобщо не е трудно.

Примери за използване

1. Основни операции

  1. //Създаване на нов обект. Можете също да пишете в процедурен стил
  2. = нов;
  3. -> свързване ("127.0.0.1", 11211) или умиране ("Не може да се свърже");
  4. //Опитайте се да получите обект с ключа our_var
  5. $var_key = @ -> get ("our_var" ) ;
  6. if (! празен ($var_key) )
  7. //Ако обектът е кеширан, отпечатайте стойността му
  8. ехо $var_key;
  9. друго
  10. //Ако в кеша няма обект с ключа our_var, създайте го
  11. //Нашият обект_var ще бъде съхранен за 5 секунди и няма да бъде компресиран
  12. -> set ("our_var" , date ("G:i:s") , false , 5 ) ;
  13. //Изходни кеширани данни
  14. echo -> get ("our_var" );
  15. ->затвори();

В резултат на изпълнението на този код всеки път ще се показва времето с точност до секунди. Той обаче ще се актуализира веднъж на всеки 5 секунди, докато кеша не бъде изчистен. Този пример илюстрира най-простите операции, но е по-вероятно да загубим производителност, отколкото да спечелим. В крайна сметка ще трябва да се свързваме със сървъра всеки път...

2. Увеличете производителността

2.1 С кеширане
  1. < ? php
  2. функция LoadCPU()
  3. //Функция, която трябва да натовари процесора
  4. $image = imagecreate(800, 600);
  5. //Бял цвят на фона
  6. $color = imagecolorallocate($image, 255, 255, 255) ;
  7. //Черно
  8. $color2 = imagecolorallocate($image, 0, 0, 0) ;
  9. за ($i = 0; $i< 10000 ; $i++ ) {
  10. imagesetpixel($image, rand (0, 800), rand (0,600), $color2);
  11. //Изхвърлете показалеца
  12. върне $изображение;
  13. //Създаване на нов обект Memcache
  14. = нов;
  15. //Свържете се с нашия сървър
  16. -> свържете ("127.0.0.1", 11211) или умрете ("Не може да се свърже");
  17. //Опитайте се да получите обект с ключовото изображение
  18. $image_bin = - > get("image" ) ;
  19. if (празно ($image_bin) ) (
  20. //Ако няма изображение в кеша, генерирайте го и го кеширайте
  21. imagepng(LoadCPU() ,getcwd() ."/tmp.png" ,9 );
  22. $image_bin = file_get_contents(getcwd() ."/tmp.png" ) ;
  23. unlink(getcwd() ."/tmp.png" ) ;
  24. -> set("image" , $image_bin, false , 30 ) ;
  25. //Извличане на изображението от кеша
  26. header("Content-type: image/png" ) ;
  27. ехо $image_bin;
  28. //Затворете връзката към Memcached сървъра
  29. -> затваряне ();
  30. ? >

Този пример показва функция, която създава изображение 800x600 и поставя 10 000 точки върху него. След като веднъж сме генерирали такова изображение, в бъдеще ние го показваме само на екрана, без да го генерираме отново.
2.2 Без кеширане
  1. функция LoadCPU()
  2. //Функция, която трябва да натовари процесора
  3. //Създаване на изображение 800x600
  4. $image = imagecreate(800, 600);
  5. //Бял цвят на фона
  6. $color = imagecolorallocate($image, 255, 255, 255);
  7. //Черно
  8. $color2 = imagecolorallocate($image, 0, 0, 0);
  9. за ($i = 0; $i< 10000 ; $i ++ ) {
  10. //Подредете 10 000 точки в произволен ред
  11. imagesetpixel($image, rand(0, 800), rand(0, 600), $color2);
  12. //Изхвърлете показалеца
  13. върне $изображение;
  14. //Показване на изображението без кеширане
  15. заглавие ("Тип съдържание: изображение/png");
  16. imagepng (LoadCPU(), "", 9);

Тук всичко е много по-просто и познато: всеки път генерираме изображението отново.
резултати
Тествах и двата скрипта за производителност. Същата машина в първия случай даде 460 отговора в секунда, а във втория само 10. Какво можеше да се очаква.

Още няколко полезни функции

addServer - ако имате няколко кеширащи сървъра на ваше разположение, можете да създадете клъстер, като добавите сървъри към пула. Трябва да обърнете внимание на параметъра тегло. Той показва колко памет ще имате на разположение на даден сървър.
delete - от името става ясно, че този метод изтрива от кеша обект с даден ключ.
replace - замества стойността на обект с даден ключ. Използвайте го, ако трябва да промените съдържанието на обект, преди да изтече жизненият му цикъл.

Долен ред

От моя гледна точка кеширането трябва да се използва само при силно натоварени ресурси. В крайна сметка всеки път, когато се свързвате със сървъра Memcached, губите ценно време, което най-вероятно няма да бъде оправдано. Що се отнася до големите проекти, по-добре е да напишете повече редове код наведнъж, отколкото да го направите набързо, с мисълта, че услугата ви лъже. Също така, не забравяйте за консумацията на памет! Моля, обърнете внимание, че като поставите 300 мегабайта в кеша, вие сте отнели 300 мегабайта RAM...
В заключение искам да кажа, че тази статия не разкрива всички прелести на технологиите, но се надявам, че ви стимулира да се самоусъвършенствате. Благодарим ви, че прочетохте, скъпи %username%!

UPD:Друг интересен момент. Memcached, има PHP API за libmemcached. И Memcache, библиотека за php, която не използва libmemcached.

Модулът Memcache предоставя удобни процедурни и обектно-ориентирани интерфейси към механизма за кеширане на memcached. Memcache е много ефективен демон за кеширане, който е специално проектиран да намали натоварването на базата данни за динамични уеб приложения с високо натоварване.

Модулът Memcache предоставя също манипулатор на сесии. Повече информация за Memcached можете да намерите на memcached.org

По принцип описанието на инсталацията и конфигурацията на руски вече е готово и можете да се запознаете с него.

Имайте предвид, че можете да съхранявате всякакъв тип данни в кеша: променливи, обекти и масиви, НО НЕ И РЕСУРСИТЕ!

Ако някой обект съдържа свойство - ресурс, например връзка към база данни, или съдържа друг обект с подобни свойства, тогава тази ситуация трябва да се третира отделно, например чрез замяна на метода __sleep(), в който този ресурс трябва да бъде „убит“ и методът __wakeup (), в който този ресурс трябва да бъде съживен.

Всъщност всички тези методи могат да бъдат разделени на 3 групи:

  1. Работа с ценности
  2. Работа със сървъри и връзки
  3. Получаване на информацията

Работа с ценности

Методите в тази група ви позволяват да направите следното:

  • Задайте стойности
  • Изтрийте тези стойности
  • Заменете тези стойности
  • Достъп до тези стойности чрез ключ
  • Управлявайте живота на стойността

Няколко специфични метода за увеличаване и намаляване на цели числа.

Memcache::set()
Memcache::add()

Позволява ви да зададете стойност, да зададете компресия и живот за тази стойност. Единствената разлика в поведението на тези методи е, че методът Memcache::add ще върне FALSE, ако вече е зададена стойност със същия ключ.

bool Memcache::add
bool Memcache::set(низ $key, смесен $var [, int $flag [, int $expire ]])

  • низ $key е ключът на стойността, като го използваме, оперираме със стойността.
  • смесена $var - стойност.
  • константи
свързване ("localhost", 11211, 30); $cache->add("myfirst", 1000, MEMCACHE_COMPRESSED, 15); $cache->set("mysecond", 2000, MEMCACHE_COMPRESSED, 15);

Memcache::get()

Връща исканата стойност или FALSE, ако не е успешно, или ако стойността с този ключ все още не е зададена.

Можете да подадете масив от ключове за стойност, след което Memcache::get също ще върне масив, който ще съдържа намерените двойки ключ-стойност.

Предупреждения!

Ако името на ключа съдържа обратна наклонена черта, тогава резултатите от работата ще бъдат непредвидими!

Memcached също има някои проблеми: според някои доклади той (понякога) податливи на грешки при препълване на буфера, което понякога води до презаписване на [частични] данни и следователно прави невъзможно десериализиране на структури, не забравяйте да проверите дали Memcache::get връща bool, dobule или long в резултат на извличане на масив или обект, тогава нещо се обърка.

низ Memcache::get(низ $key [, int &$flags ])
масив Memcache::get(масив $ключове [, масив &$знамена])

  • низ $key - стойностен ключ или масив от ключове, чиито стойности трябва да бъдат получени.
  • int $flag - целта на този параметър остава загадка за мен. Опитах да използвам някои цели числа, но нямаше ефект. И примерите са дадени предимно без да го използвате, от което заключих, че можете да работите добре и без него :)
свързване ("localhost", 11211, 30); $cache->add("myfirst", 1000, MEMCACHE_COMPRESSED, 15); $cache->set("mysecond", 2000, MEMCACHE_COMPRESSED, 15); print_r($cache->get(array("myfirst","mysecond")));

Резултат:

Масив ( => 1000 => 2000)

Memcache::delete()

Премахване на стойност от кеша.

коментар:

Този метод не винаги работи (Зависи от версията на софтуера)! В края на страницата има случаи, когато Memcache::delete работи и когато не работи.

Е, единствената стабилна опция е да нулирате ненужните стойности:

$cache->set("три", NULL);

Има само един минус - ключът в този случай не отива никъде

низ Memcache :: изтриване(низ $key [, int $timeout = 0 ])

  • низ $key - стойността на ключа за изтриване.
  • int $timeout - Този параметър също е отхвърлен и не се поддържа, по подразбиране е 0 секунди. Не използвайте тази опция.

Memcache::replace()

Презаписване на съществуваща стойност.

Memcache::replace() трябва да се използва за замяна съществуваща стойност. Ако стойност с такъв ключ не съществува, Memcache::replace() връща FALSE. В противен случай Memcache::replace() се държи по същия начин като Memcache::set(). Можете също да използвате функцията memcache_replace().

низ Memcache::replace(низ $key, смесен $var [, int $flag [, int $expire ]])

  • низ $key - ключът, чиято стойност трябва да бъде заменена.
  • смесен $var - нова стойност.
  • int $flag - Флаг, показващ дали да се използва компресия (Тук идва Zlib) за съхранената стойност, могат да се използват константи
  • int $expire - Живот на стойността (кеш). Ако е равно на нула, тогава за неопределено време. Можете също да използвате клеймо за време или брой секунди от текущия час, но тогава броят секунди не може да надвишава 2592000 (30 дни).
свързване ("localhost", 11211, 30); $cache->add("едно", 111, 0, 15); $cache->add("две", 222, 0, 15); $cache->add("три", 333, 0, 15); $cache->replace("три", 777); print_r($cache->get(array("one","two","three"))); Масив ( => 111 => 222 => 777)

Memcache::increment()

Увеличава стойността на посочения ключ с посочената стойност. Ако стойността на посочения ключ не е числова и не може да бъде преобразувана в число, тогава той ще промени стойността си на стойността, посочена като втори параметър. Memcache::increment() не създава елемент, ако той вече не съществува.

Не се препоръчва използването на Memcache::increment() със стойности, които са били компресирани (зададени с флага MEMCACHE_COMPRESSED), защото ще има изненади по-късно, когато се опитате да получите тези стойности с помощта на Memcache::get()

Лично аз проверих и не забелязах никакви проблеми :)

вътр Memcache::увеличение

  • низ $key - ключът, чиято стойност трябва да се увеличи.
  • int $value - увеличава стойността.
свързване ("localhost", 11211, 30); $cache->set("someOne", 10, 0, 5); $cache->increment("someOne", 10, 0, 5); $cache->increment("someOne", 10, 0, 5); echo $cache->get("someOne");// ще отпечата 30

Memcache::decrement()

Намалява стойността на посочения ключ с посочената стойност. Подобно на Memcache::increment(), текущата стойност на елемента се преобразува в числова стойност и след това се намалява

вътр Memcache::декремент(низ $key [, int $value = 1 ])

  • низ $key - ключът, чиято стойност трябва да бъде намалена.
  • int $value - намалява стойността.

Memcache::flush()

Memcache::flush() обезсилва всички съществуващи стойности. Memcache::flush() всъщност не освобождава ресурси на паметта, той само маркира всички елементи като остарели, така че заетата памет да бъде достъпна за използване от нови стойности. Също така можете да използвате функцията memcache_flush().

bool Memcache::flush(недействителен)

Примерът по-долу няма да изведе нищо.

свързване ("localhost", 11211, 30); $cache->set("someOne", 111, 0, 5); $cache->set("someTwo", 222, 0, 5); $cache->set("someTree", 333, 0, 5); $cache->flush(); //Изчиства кеша print_r($cache->get(array("someOne","someTwo","someTree")));

Работа със сървъри и връзки.

Memcache може да работи както с един сървър, така и с набор (набор) от сървъри.

Ако използвате само един сървър за обслужване на кеша, тогава за инициализиране на работата ще трябва само да създадете кеш обект и да използвате метода Memcache::connect

Ако възнамерявате да създадете набор от сървъри, тогава ще трябва първо да създадете кеш обект и след това да използвате Memcache::addServerдобавете необходимия брой сървъри към него.

Memcache::connect()

Установява връзка със сървъра Memcached. Връзка, която е била отворена с помощта на Memcache::connect(), ще бъде затворена автоматично, когато скриптът завърши, но можете да я затворите изрично с помощта на Memcache::close(). Можете също да използвате функцията memcache_connect() Връща TRUE при успех или FALSE при грешка.

bool Memcache::connect

свързване ("localhost", 11211, 30);

Memcache::pconnect()

Този метод е подобен на Memcache::connect() с единствената разлика, че установява постоянна връзка. Тази връзка не се затваря, когато скриптът завърши и се извика Memcache::close(). Можете също да използвате функцията memcache_pconnect() Връща обект Memcache при успех или FALSE при грешка.

смесен Memcache::pconnect(низ $host [, int $port [, int $timeout ]])

  • Този параметър може също да указва други транспорти като unix:///path/to/memcached.sock, т.е. използвайте UNIX сокети, в който случай портът трябва да бъде зададен на 0.
  • Задайте този параметър на 0, ако възнамерявате да използвате гнезда.
  • int $timeout - Ограничение в секунди за свързване към демона. Помислете два пъти, преди да промените стойността по подразбиране от 1 секунда - може да загубите всички предимства на кеширането, ако връзката ви отнеме твърде дълго.
pconnect("localhost", 11211, 30);

Memcache::close()

Затваря връзката със сървъра Memcached. Тази функция не затваря постоянните връзки, които се затварят само когато уеб сървърът се изключи/рестартира. Можете също да използвате функцията memcache_close().

bool Memcache :: затвори(недействителен)

Memcache::addServer()

Добавя сървър към пула за връзки. Връзка, която е била отворена с помощта на Memcache::addServer(), ще бъде затворена автоматично, когато скриптът завърши, или можете да я затворите ръчно с Memcache::close(). Можете да използвате функцията memcache_add_server().

Когато използвате Memcache::addServer (за разлика от Memcache::connect() и Memcache::PConnect()), мрежовата връзка не се установява, докато не е действително необходима. По този начин няма режийни разходи при добавяне на голям брой сървъри към пула, дори ако те изобщо не са необходими.

Сървърният пул осигурява по-висока устойчивост на грешки. Всякакви грешки в сокета или Memcached грешки на ниво сървър (различни от грешки в паметта) причиняват преразпределяне на ресурси. Грешки на клиента като добавяне на съществуващ ключ няма да причинят неуспехи.

коментар:

Връща TRUE при успех или FALSE при грешка.

bool Memcache::addServer(низ $host [, int $port = 11211 [, bool $persistent [, int $weight [, int $timeout [, int $retry_interval [, bool $status [, callable $failure_callback [, int $timeoutms ]]]] ]]]])

  • низ $host - Memcached хост. Този параметър може също да указва други транспорти като unix:///path/to/memcached.sock, т.е. използвайте UNIX сокети, в който случай портът трябва да бъде зададен на 0.
  • int $port - портът, на който Memcached слуша за връзки. Задайте този параметър на 0, ако възнамерявате да използвате гнезда.
  • bool $persistent - Задава използването на постоянна връзка. По подразбиране е TRUE.
  • int $weight - Колкото по-голяма е стойността, толкова по-вероятно е този сървър да бъде избран да съхранява стойностите. Тези. това е един вид "тежест" на сървъра в общия пул, косвено това е и очакваното натоварване на сървъра.
  • int $timeout - Ограничение в секунди за свързване към демона. Помислете два пъти, преди да промените стойността по подразбиране от 1 секунда - може да загубите всички предимства на кеширането, ако връзката ви отнеме твърде дълго.
  • низ $timeoutms - не е описано.

Получаване на информацията

Memcache::getExtendedStats()

Връща двуизмерен асоциативен масив от статистически данни на сървъра. Масив от сървърни ключове хост:порт. Стойностите съдържат индивидуални статистически параметри. Неуспешните сървъри ще имат стойност FALSE. Можете също да използвате функцията memcache_get_extended_stats().

коментар:

Тази функция беше добавена към Memcache във версия 2.0.0

масив Memcache::getExtendedStats([ низ $type [, int $slabid [, int $limit = 100 ]]])

А сега една шега:

Типът статистика "cachedump" е премахнат от Memcached от съображения за сигурност

Пример за извеждане на информация (обаждане без параметри):

Масив ( => 5179 => 966862 => 1336505233 => 1.4.5 => 64 => 160.302880 => 483.975109 => 6 => 358080 => 13 => 15037476 => 3501979 => 46 => 11507898 => 3529578 => 0 => 0 => 0 => 76 => 0 => 0 => 0 => 0 => 0 => 0 => 0 => 1643906080 => 11298732744 => 67108864 => 1 => 0 => 4 => 0 => 3295454 => 7623 => 3501915 => 0 => 1825755) ...)

Memcache::getServerStatus()

Връща онлайн/офлайн състоянието на сървъра. Можете също да използвате функцията memcache_get_server_status()

коментар:

Тази функция беше добавена към Memcache във версия 2.0.0

вътр Memcache::getServerStatus(низ $host [, int $port = 11211 ])

  • низ $host - Memcached хост.
  • int $port - портът, на който Memcached слуша за връзки.

Memcache::getStats()

Връща асоциативен масив със статистика на сървъра. Масив от ключове, съответстващи на статистически параметри и стойности за стойността на параметъра. Можете също да използвате функцията memcache_get_stats()

масив Memcache::getStats s ([ низ $type [, int $slabid [, int $limit = 100 ]]])

  • string $type - тип статистика. Валидни стойности: (reset, malloc, maps, cachedump, slabs, items, sizes). Според спецификацията на протокола Memcached, тези допълнителни аргументи „могат да бъдат модифицирани за удобство на разработчиците“.
  • int $slabid - Използва се, когато първият параметър е зададен на "cachedump" указва сървъра, който да се използва за отстраняване на грешки.
  • int $limit - Използва се, когато първият параметър е зададен на "cachedump", за да ограничи броя на записите в дъмпа.

Memcache::getVersion()

Връща низ - номера на версията на сървъра. Можете също така да използвате функцията memcache_get_version().

низ Memcache::getVersion(недействителен)

Memcache::setCompressThreshold()

Осигурява автоматично компресиране на големи стойности. Можете също да използвате функцията memcache_set_compress_threshold()

коментар:

Тази функция беше добавена към Memcache във версия 2.0.0

bool Memcache::setCompressThreshold(int $threshold [, float $min_savings ])

  • int $threshold - Минимална дължина на стойността, която трябва да бъде компресирана автоматично.
  • float $min_savings - Задава съотношението на компресия. Посочената стойност трябва да бъде между 0 и 1. Стойността по подразбиране е 0,2, което дава минимум 20% икономия на компресия.

Memcache::setServerParams()

Променя параметрите на сървъра по време на изпълнение. Можете също да използвате функцията memcache_set_server_params().

Връща TRUE при успех или FALSE при грешка.

коментар:

Тази функция беше добавена към Memcache във версия 2.0.0

bool Memcache::setServerParams(низ $host [, int $port = 11211 [, int $timeout [, int $retry_interval = false [, bool $status [, извикваем $failure_callback ]]]]])

  • низ $host - Memcached хост.
  • int $port - портът, на който Memcached слуша за връзки.
  • int $timeout - Ограничение в секунди за свързване към демона. Помислете два пъти, преди да промените стойността по подразбиране от 1 секунда - може да загубите всички предимства на кеширането, ако връзката ви отнеме твърде дълго.
  • int $retry_interval - Задава колко често да се запитва неуспешен сървър, стойността по подразбиране е 15 секунди. Задаването на този параметър на -1 деактивира автоматичния повторен опит за заявки.
  • bool $status - Маркира сървъра като ОНЛАЙН. Задаването на този параметър на FALSE и retry_interval -1 позволява неуспешният сървър да бъде запазен в група от активни сървъри, така че да не се засягат алгоритмите за разпределение на ключове. Заявките към този сървър ще бъдат разпределени между останалите налични сървъри. Стойността по подразбиране е TRUE, което означава, че сървърът трябва да се счита за ОНЛАЙН.
  • callable $failure_callback - Позволява на потребителя да посочи функция за обратно извикване, която да се изпълнява, когато бъде открита грешка. Функцията трябва да приема два параметъра, името на хоста и порта на неуспешния сървър.

С тази публикация искам да отворя малка поредица от публикации, базирани на материалите от доклада на HighLoad++-2008. Впоследствие целият текст ще бъде публикуван като един голям PDF файл.

Въведение

Първо, относно заглавието на поредицата от публикации: публикациите ще бъдат за кеширане в мрежата (в уеб проекти с голямо натоварване) и за използването на memcached за кеширане, както и за други употреби на memcached в уеб проекти. Тоест и трите компонента на името в различни комбинации ще бъдат обхванати в тази поредица от публикации.

Кеширането днес е неразделна част от всеки уеб проект, не непременно такъв с високо натоварване. За всеки ресурс критична характеристика за потребителя е времето за отговор на сървъра. Увеличаването на времето за реакция на сървъра води до отлив на посетители. Следователно е необходимо да се сведе до минимум времето за отговор: за това е необходимо да се намали времето, необходимо за генериране на отговор на потребителя, а отговорът на потребителя изисква получаване на данни от някои външни ресурси (backend). Тези ресурси могат да бъдат или бази данни, или всякакви други относително бавни източници на данни (например отдалечен файлов сървър, на който проверяваме количеството свободно пространство). За да генерираме една страница от доста сложен ресурс, може да се наложи да направим десетки подобни обаждания. Много от тях ще бъдат бързи: 20 ms или по-малко, но винаги има малък брой заявки, чието време за изчисление може да се изчисли в секунди или минути (дори в най-оптимизираната система може да има такава, въпреки че техният брой трябва да е минимален) . Ако съберем цялото време, което прекарваме в чакане на резултати от заявката (ако изпълняваме заявки паралелно, ще вземем времето за изчисление на най-дългата заявка), ще получим незадоволително време за отговор.

Решението на този проблем е кеширането: ние поставяме резултата от изчисленията в някакво хранилище (например memcached), което има отлични характеристики по отношение на времето за достъп до информация. Сега, вместо да имаме достъп до бавни, сложни и тежки бекендове, просто трябва да направим заявка към бързия кеш.

Memcached и кеширане

Принцип на локалност

Виждаме кеша или подхода за кеширане навсякъде в електронните устройства и софтуерната архитектура: кеш на процесора (първо и второ ниво), буфери на твърдия диск, кеш на операционната система, буфер в радиото на колата. Какво определя такъв успех на кеширането? Отговорът се крие в принципа на локалността: програма или устройство има тенденция да работи с определено подмножество от данни от общия набор за определен период от време. В случая с RAM това означава, че ако една програма работи с данни, намиращи се на адрес 100, то с по-голяма степен на вероятност следващият достъп ще бъде на адрес 101, 102 и т.н., а не на адрес 10000 например. Същото е и с твърдия диск: неговият буфер се запълва с данни от области, съседни на последните прочетени сектори, ако нашите програми са работили в даден момент не с някакъв относително малък набор от файлове, а с цялото съдържание на твърдия диск. , буферите биха били безсмислени. Буферът на стерео уредбата на автомобила чете преди следващите минути музика от диска, защото е по-вероятно да слушаме музикален файл последователно, отколкото да прескачаме през набор от музика и т.н.

В случай на уеб проекти, успехът на кеширането се определя от факта, че сайтът винаги има най-популярните страници, някои данни се използват на всички или почти всички страници, тоест има някои селекции, които се изискват много по-често отколкото други. Заменяме няколко извиквания към бекенда с едно извикване за изграждане на кеш и след това всички следващи извиквания ще бъдат направени чрез бързо работещ кеш.

Кешът винаги е по-добър от оригиналния източник на данни: Кешът на процесора е с порядъци по-бърз от RAM, но не можем да направим RAM толкова бърз, колкото кеша – това е икономически неефективно и технически предизвикателно. Буферът на твърдия диск задоволява заявките за данни с порядък по-бързо от самия твърд диск, но буферът няма способността да запомня данни, когато захранването е изключено - в този смисъл той е по-лош от самото устройство. Подобна е ситуацията с кеширането в мрежата: кешът е по-бърз и по-ефективен от бекенда, но обикновено в случай на рестартиране или срив на сървъра, той не може да запази данни и също така няма логиката за изчисляване на резултати: може да върне само това, което преди това сме поставили в него.

Memcached

Memcached е огромна хеш таблица в паметта, достъпна през мрежов протокол. Той предоставя услуга за съхраняване на стойности, свързани с ключове. Ние осъществяваме достъп до хеша чрез прост мрежов протокол; клиентът може да бъде програма, написана на произволен език за програмиране (има клиенти за C/C++, PHP, Perl, Java и др.).

Най-простите операции са получаване на стойността на посочения ключ (get), задаване на стойността на ключа (set) и изтриване на ключа (del). За да се приложи верига от атомарни операции (предмет на паралелен достъп до memcached от паралелни процеси), се използват допълнителни операции: увеличаване/намаляване на ключова стойност (incr/decr), добавяне на данни към ключовата стойност в началото или края (прибавяне /prepend), атомно свързване получаване/задаване на стойности (gets/cas) и други.

Memcached е внедрен от Брад Фицпатрик като част от работата му по проекта LiveJournal. Използва се за освобождаване на базата данни от заявки при обслужване на съдържание на страница. Днес memcached намери своето приложение в основата на много големи проекти, например Wikipedia, YouTube, Facebook и други.

Като цяло схемата за кеширане изглежда така: интерфейсът (частта от проекта, която генерира отговора на потребителя) трябва да получи данни от някаква проба. Frontend се свързва с cheetah-fast memcached сървъра за кеша за извличане (заявка за получаване). Ако съответният ключ бъде намерен, работата приключва дотук. В противен случай трябва да се обърнете към тежък, тромав, но мощен (като слон) бекенд, който най-често е база данни. Полученият резултат незабавно се записва в memcached като кеш (set request). В този случай на ключа обикновено се дава максимален живот (дата на изтичане), който съответства на момента на нулиране на кеша.

Тази стандартна схема за кеширане винаги се прилага. Вместо memcached, някои проекти могат да използват локални файлове или други методи за съхранение (друга база данни, кеш на PHP ускорителя и т.н.) Въпреки това, както ще бъде показано по-долу, в проект с голямо натоварване тази схема може да не работи по най-ефективния начин . Въпреки това в по-нататъшната ни история ще разчитаме на тази схема.

memcached архитектура

Как работи memcached? Как успява да работи толкова бързо, че дори десетки заявки към memcached, необходими за обработка на една страница от сайта, не водят до значително забавяне. В същото време memcached е изключително неизискващ по отношение на изчислителните ресурси: при заредена инсталация процесорното време, което използва, рядко надвишава 10%.

Първо, memcached е проектиран така, че всички негови операции да имат алгоритмична сложност O(1), т.е. времето за изпълнение на всяка операция не зависи от броя на ключовете, които memcached съхранява. Това означава, че някои операции (или възможности) ще липсват, ако изпълнението им изисква само линейно (O(n)) време. По този начин memcached няма способността да комбинира ключове „в папки“, т.е. всяко групиране на ключове и няма да намерим групови операции върху ключове или техните стойности.

Основните оптимизирани операции са разпределяне/освобождаване на блокове памет за съхраняване на ключове, дефиниране на политика за най-малко използвани ключове (LRU) за изчистване на кеша, когато няма достатъчно памет. Търсенето на ключове става чрез хеширане, така че има сложност O(1).

Използва асинхронен I/O и не използва нишки, което осигурява допълнителни печалби в производителността и по-ниски изисквания за ресурси. Всъщност memcached може да използва нишки, но това е необходимо само за използване на всички налични ядра или процесори на сървъра в случай на твърде голямо натоварване - във всеки случай нишка не се създава за всяка връзка.

Всъщност можем да кажем, че времето за отговор на memcached сървъра се определя само от мрежовите разходи и е почти равно на времето, необходимо за предаване на пакет от интерфейса към memcached сървъра (RTT). Такива характеристики правят възможно използването на memcached в уеб проекти с голямо натоварване за решаване на различни проблеми, включително кеширане на данни.

Изгубени ключове

Memcached не е надеждно хранилище; възможно е даден ключ да бъде премахнат от кеша преди да изтече срокът му на живот. Архитектурата на проекта трябва да е подготвена за такава ситуация и да реагира гъвкаво на загуба на ключове. Има три основни причини за загуба на ключове:
  1. Ключът е изтрит преди датата на изтичане поради недостатъчна памет за съхраняване на стойностите на други ключове. Memcached използва LRU политика, така че тази загуба означава, че ключът е използван рядко и кеш паметта се освобождава за съхраняване на по-популярни ключове.
  2. Ключът беше изтрит, защото животът му е изтекъл. Тази ситуация, строго погледнато, не е загуба, тъй като ние сами ограничихме живота на ключа, но за клиентския код по отношение на memcached такава загуба е неразличима от други случаи - при достъп до memcached получаваме отговора „там няма такъв ключ.
  3. Най-неприятната ситуация е сривът на процеса memcached или сървъра, на който се намира. В тази ситуация губим всички ключове, които са били съхранени в кеша. Организацията на клъстера ви позволява донякъде да изгладите последствията: много memcached сървъри, върху които ключовете на проекта са „разпръснати“: по този начин последствията от срива на един кеш ще бъдат по-малко забележими.

Всички описани ситуации трябва да се имат предвид при разработването на софтуер, който работи с memcached. Можем да разделим данните, които съхраняваме в memcached, според тежестта на тяхната загуба.

"Можеш да го загубиш". Тази категория включва кешове на селекции от бази данни. Загубата на такива ключове не е толкова лоша, защото можем лесно да възстановим техните стойности чрез нов достъп до бекенда. Честите загуби на кеш обаче водят до ненужни извиквания на база данни.

„Не бих искал да загубя“. Тук можете да посочите броячи на посетители на сайта, прегледи на ресурси и т.н. Въпреки че понякога е невъзможно тези стойности да се възстановят директно, стойностите на тези ключове имат ограничено във времето значение: след няколко минути тяхната стойност вече не е релевантна и ще бъде изчислена нова стойност.

„Изобщо не трябва да губим“. Memcached е удобен за съхраняване на потребителски сесии - всички сесии са еднакво достъпни от всички сървъри, включени в фронтенд клъстера. Така че никога не бих искал да загубя съдържанието на сесиите - в противен случай потребителите на сайта ще бъдат „излезли“. Как да се опитате да избегнете? Можете да дублирате сесийни ключове на няколко memcached сървъра от клъстер, така че вероятността от загуба е намалена.

Всеки повече или по-малко развиващ се уеб проект рано или късно среща проблеми, които най-добре се решават с помощта на кеширане. Например запазване на обобщени данни в някакво хранилище, чието изчисляване и/или извличане отнема много време. Има няколко опции за кеширане на данни: запис на данни на диск или в RAM. Всеки вариант има своите плюсове и минуси. Записването на диск е бавно; записът се извършва последователно с помощта на ключалки, чийто брой обикновено е ограничен от операционната система. Но данните се запазват завинаги и ще бъдат достъпни след рестартиране на сървъра. RAM, напротив, е бърза, без ключалки, но не се запазва в случай на рестартиране. Опасно е да се съхраняват недублирани данни в него. Ако всичко е ясно и просто със записването на диск, тогава работата с паметта е по-сложна. Има приложения, които поемат тази задача. Един от които е Memcached. В тази статия ще говорим за това.

Memcached е сървър с отворен код, който ви позволява да кеширате данни в RAM. Има висока скорост. Популярен. Има голям набор от клиентски библиотеки, написани на различни езици за програмиране.

В Php има две версии на библиотеки: php-memcache и php-memcached. Първият е стар и вече не се развива. Вторият е нов и има по-голям набор от функции. Има повече разлики между тях и зависи от вас да решите коя да използвате. Тази статия ще използва php-memcached.

За да опознаем по-добре memcached, нека създадем малко приложение, което се възползва от основните му възможности. Ще напишем защита срещу отгатване на парола по време на авторизация. Същността на приложението ще бъде, че ако опитите за оторизация са неуспешни, приложението ще съхранява броя на неуспешните опити в кеша. Когато този брой надвиши зададения минимум, възможността за авторизация ще бъде блокирана за определено време. За 2-3 минути. В този случай значително намаляваме ефективността на отгатването на паролата.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 изисквам_веднъж __DIR__. "/func.php" ; if (! extension_loaded ("memcached" ) ) ( die ( „Разширението Memcached не е инсталирано“) ; ) $USE_CACHE_PROTECTION = вярно ; $AUTH_MAX_ATTEMPTS = 5; $AUTH_LOGIN = "демо" ; $AUTH_PASSWORD = "демо" ; $грешка = масив (); if (IS_POST() ) ( $login = _POST("username" ) ; $password = _POST("password" ) ; if (! $login ) ( $error [ "username" ] = "required" ; ) if (! $password ) ( $error [ "password" ] = "required" ; ) // INIT MEMCACHE if ($USE_CACHE_PROTECTION ) ( $cache = new Memcached() ; $cache -> addServer ( "127.0.0.1" , 11211 ) ); $cacheKey = "prefix::login-protect-" . $login ; //проверка на защитата на кеша ако ($USE_CACHE_PROTECTION && ! $error) ($attempts = $cache -> get ($cacheKey) ; // ПРОВЕРКА НА НЕУСПЕШНИ ОПИТИ ако ($attempts >= $AUTH_MAX_ATTEMPTS ) ( $error [ "global" ] = "max_attempts" ; ) ) //проверете auth if (! $error ) ( //TODO: използвайте db bro if ($login == $AUTH_LOGIN && $password == $AUTH_PASSWORD ) ( // ИЗЧИСТВАНЕ НА ДАННИ ПРИ УСПЕХ AUTH if ($USE_CACHE_PROTECTION ) ( $cache -> delete ($cacheKey ) ; ) stopAndRedirect("success.php" ) ; ) if ($USE_CACHE_PROTECTION ) ( / / ОПИТИ ЗА УВЕЛИЧАВАНЕ if (! $cache -> увеличение ($cacheKey) ) ( $cache -> set ($cacheKey, 1, 60)); ) ) $error [ "global" ] = "auth_faild" ; ) )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

Демо за използване на memcached в php

Упълномощаване


Както можете да видите от кода, всичко е изключително просто. Създава се уникален ключ, състоящ се от префикса на сайта, името на задачата и въведените данни за вход. След това четем, увеличаваме брояча, изтриваме. Струва си да се обърне внимание на частта от кода, където скриптът увеличава брояча на неуспешните опити за оторизация. Методът на нарастване се връща невярноако няма запис в memcached. Следователно, в случай на повреда, задаваме записа със стойност 1 за точно 60 секунди.

Струва си да се съсредоточим върху факта, че използваме метода на нарастване, а не set(getted_value+1) . Работата е там, че зададеният метод не дава възможност за правилно увеличаване на брояча, тъй като данните могат да се променят между интервалите за четене и запис. Например, в същото време друг потребител също ще познае паролата. Гарантирано е, че методът на нарастване увеличава правилно брояча!

В резултат на прилагане на информацията, дадена в тази статия, вие ще можете да инсталирате и конфигурирате сървъра Memcached и необходимото php разширение за взаимодействие с него, както и услугата за анализ и статистика phpMemcachedAdmin

Инсталацията ще се извърши под Debian с бекенд сървър. Ако имате работещ пакет + php5-fpm, просто заменете apache2 с php5-fpm в командите
Работни инструменти: файлов мениджър за свързване на софтуер с вграден редактор или putty.

Сега да кажем, че вече имаме уебсайт http://example.com на този хостинг

Първо, трябва да определите как е конфигуриран PHP (какво ще стане, ако Memcached вече е инсталиран?)). За целта в корена на сайта ще създадем временно файл info.php с кода

Сега нека го разгледаме http://example.com/info.php

Ако видим, че има подобен запис, значи всичко е наред, необходимото php разширение е инсталирано.
Ако не, тогава трябва да работите.

Как да инсталирате Memcached сървър

Преди инсталиране трябва да актуализирате хранилището

Apt-get актуализация && apt-get надстройка

Сега нека инсталираме memcached и php модула за него

Apt-get инсталира memcached php5-memcache

Инсталацията е в ход. След приключването му проверяваме какво се е случило

В резултат на това ще видим нещо подобно

Tcp 0 0 *:11211 *:* СЛУШАЙТЕ 13053/memcached

Сега трябва да рестартирате Apache или php-fpm

Рестартиране на услугата apache2

Настройване на Memcached

Сега, когато сървърът е инсталиран, той трябва да бъде конфигуриран. Не е трудно и няма да отнеме много време

Затваряне на Memcached от външен достъп

Както можете да видите, memcached виси на порт 11211 по подразбиране. Тъй като memcached няма вградени механизми за удостоверяване, се оказва, че всеки може да се свърже отвън и да го използва за свои собствени цели. За да избегнете това, можете или да затворите порт 11211 с помощта на защитна стена, или да конфигурирате memcached сървъра, така че да може да се използва само от localhost. Последният метод е описан по-долу.

  1. Добавете реда -l 127.0.0.1
  2. Рестартирайте memcached

    Рестартиране на услугата memcached

    /etc/init.d/memcached рестартиране

И пак проверяваме

Netstat -докоснете | grep memcached

В крайна сметка трябва да видим нещо подобно

Tcp 0 0 localhost.localdo:11211 *:* СЛУШАЙТЕ 13092/memcached

Също така, след всички промени, не забравяйте да рестартирате Apache

Рестартиране на услугата apache2

Увеличаване на обема на работната памет Memcached

По подразбиране Memcached е разпределен да използва 64 мегабайта RAM. Ще увелича до 1024, вие изхождайте от параметрите на вашия сървър

  1. Отворете конфигурационния файл на vi /etc/memcached.conf
  2. Намерете стойността -m 64
  3. Променете го на -m 1024
  4. Рестартирайте услугата memcached memcached рестартирайте

Съхраняване на PHP сесии в Memcached

Ако няколко различни сайта използват един и същ Memcached сървър или клъстер, те могат да прихващат сесиите на другия и да получат достъп до своите потребителски акаунти, което представлява потенциална опасност

Можете да ускорите PHP, като преместите хранилището на сесиите от hdd към RAM с помощта на memcached

Трябва да знаете кое php разширение използвате, memcache или memcached. , и можете да разберете какво имате с помощта на phpinfo(), има тънкости в настройките, внимавайте

Метод за разширяване на memcache

  1. Отворете /etc/php5/mods-available/memcache.ini
  2. Добавете session.save_handler = memcache session.save_path = "tcp://127.0.0.1:11211"

Метод за разширяване на memcacheD

  1. Отворете /etc/php5/mods-available/memcached.ini
  2. Добавете session.save_handler = memcached session.save_path = "127.0.0.1:11211"
  3. Рестартирайте услугата apache apache2 рестартирайте

Проверка на phpinfo

Сега трябва да проверим какво имаме на изхода. За да направите това, отворете страницата с phpinfo() и потърсете session.save_path в кода в колоната с локални стойности. Стойността трябва да бъде tcp://127.0.0.1:11211 или 127.0.0.1:11211 ..conf), и ние търсим
php_admin_value session.save_path

Между другото, можете също да използвате директивата php_value, за да конфигурирате не целия сървър глобално, а само конкретни сайтове. За да направите това, можете да редактирате .htaccess в корена на вашия сайт

Php_value session.save_handler "memcache" php_value session.save_path "tcp://127.0.0.1:11211"

Готов работещ Memcached конфигурационен файл

Можете също така да персонализирате всичко, за да отговаря на вашите нужди, конфигурационният файл съдържа подробни коментари:

# memcached конфигурационен файл по подразбиране # 2003 - Джей Бончи< ># Този конфигурационен файл се чете от скрипта start-memcached, предоставен като # част от дистрибуцията на Debian GNU/Linux. # Стартирайте memcached като демон. Тази команда се подразбира и не е необходима за стартиране на демона #. Вижте README.Debian, който идва с този пакет за повече # информация. -d # Регистрирайте изхода на memcached в /var/log/memcached logfile /var/log/memcached.log # Бъдете многословни # -v # Бъдете още по-подробни (отпечатайте и клиентски команди) # -vv # Започнете с капачка от 64 мегабайта памет. Това е разумно и демонът по подразбиране # Имайте предвид, че демонът ще нарасне до този размер, но не започва да държи толкова много # памет # Количеството памет в мегабайти, което е разпределено за кеширане. По подразбиране 64 мегабайта. #-m 64 -m 1024 # Портът, на който Memcached ще виси, по подразбиране 11211 -p 11211 # Стартирайте демона като root. Start-memcached ще работи по подразбиране като root, ако в този конфигурационен файл няма команда # -u -u memcache # Посочете кой IP адрес да слушате. По подразбиране се прослушват всички IP адреси # Този параметър е една от единствените мерки за сигурност, които memcached има, така че се уверете # че той слуша интерфейс със защитна стена. -l 127.0.0.1 # Ограничете броя на едновременните входящи връзки. Демонът по подразбиране е 1024 # # -c 1024 # Заключете цялата странирана памет, преди да направите това # -k # Връщане на грешка, когато паметта е изчерпана (вместо премахване на елементи) # -M # Максимизиране на основния файл. ограничение # -r

Инсталиране на разширението memcache

По-долу са дадени команди стъпка по стъпка, които ще ви помогнат да инсталирате PHP разширението memcache от конзолата ръчно

Apt-get инсталирате php5-dev libmemcache-dev pecl изтегляне memcache tar xzvf memcache-2.2.6.tgz cd memcache-2.2.6/ phpize && ./configure --enable-memcache && make cp modules/memcache.so /usr/ lib/php5/20060613/ echo "разширение=memcache.so" >> /etc/php5/apache2/php.ini

Рестартирайте Apache, за да влязат в сила промените.

Рестартиране на услугата apache2

Как да проверите дали Memcached работи

Нека създадем файл memcachetest.php в корена на сайта и да напишем следния код там

connect("localhost", 11211) или exit("Не може да се свърже със сървъра Memcached"); $version = $memcache->getVersion(); echo "Версия на сървъра: ".$version."
\n"; $tmp_object = нов stdClass; $tmp_object->str_attr = "тест"; $tmp_object->int_attr = 123; $memcache->set("ключ", $tmp_object, false, 10) или умре ("Не Успях да оставя запис в Memcached"); echo "Записваме данни в кеша на Memcached (данните ще се съхраняват за 10 секунди)
\n"; $get_result = $memcache->get("ключ"); echo "Данни, записани в Memcached:
\n"; var_dump($get_result); ?>

Сега остава само да проверите резултатите: http://example.com/memcachetest.php
Ако сте направили всичко правилно, ще видите нещо подобно

phpMemcachedAdmin - мониторинг, статистика и управление на Memcached

phpMemcachedAdmin е софтуер, който предоставя уеб интерфейс за наблюдение и управление на услугата Memcached на Linux. Позволява ви да видите статистика в реално време за всички операции, поддържани от сървъра: получаване, настройка, изтриване, увеличаване, намаляване, възстановяване, изгонвания, cas, както и статистика на сървъра: мрежа, позиции, работеща версия, съчетана с диаграми и вътрешни конфигурация на сървъра.

Инсталиране и конфигуриране на phpMemcachedAdmin

Тук можете да отидете по няколко начина: разпределете отделен домейн или поддомейн за работата на тази услуга. Или можете да направите поддиректория на работния си сайт и да поставите парола в нея или . Ще опиша последния метод за задаване на парола за папка като по-прост.

И така, да кажем, че имаме сайт https://site

CD /var/www/сайт

Създайте директория и отидете в нея

Mkdir phpMemcachedAdmin && cd phpMemcachedAdmin

Изтеглете най-новата версия на дистрибуцията

Wget http://phpmemcacheadmin.googlecode.com/files/phpMemcachedAdmin-1.2.2-r262.tar.gz

Разопаковайте и изтрийте архива за разпространение

Tar -xvzf phpMemcachedAdmin-1.2.2-r262.tar.gz && rm -rf phpMemcachedAdmin-1.2.2-r262.tar.gz

Рекурсивно задайте необходимите права за достъп в текущата директория

Find ./ -type f -exec chmod 0644 () \; намери ./ -тип d -exec chmod 0755 () \;

AuthType Basic AuthName "Private Area" AuthUserFile .htpasswd Изискване на потребител memcachedmanager

Create.htpasswd

Htpasswd -c .htpasswd memcachedmanager

Въведете паролата си.

Това е всичко. Влезте в директорията memcachedmanager, ако не сте я променили. Отворете https://site/phpMemcachedAdmin (променете домейна на вашия), въведете вашето потребителско име/парола и използвайте

Накрая

Препоръчвам да прочетете статията за memcached. Разкрива обща информация за него и някои от тънкостите на работата му.
Това е всичко. Ако нещо не е ясно, задавайте въпроси в коментарите.



Дял