Memcached in PHP – o solutie NoSQL
11Cati dintre noi folosesc altceva in afara de o baza de date clasica, gen MySQL in proiectele noastre web? Probabil, foarte putini. Intradevar, puterea unei astfel de baze de date este imensa, avand in vedere si faptul ca ele sunt construite sa reziste la cereri foarte mari. Totusi, uneori e bine sa folosim in cadrul website-ului nostru si alternative NoSQL.
Ce este NoSQL?
Avand in vedere ca este prima data cand folosesc acest termen pe blog, ma voi concentra si asupra explicarii acestui fenomen. Avand in vedere ca ne raportam la baze de date clasice, relationale, trebuie sa stim ca operatiile ce consuma cel mai mult timp intr-un tabel de acest gen sunt joinurile. NoSQL, se refera mai exact la NotOnlySQL. Practic vii cu alternative care sunt avantajoase spre exemplu in cazul in care ai foarte multe operatii scriere/citire.
Ce este Memcached?
Memcached este un sistem de caching distribuit ce poate fi folosit Windows, MacOS si Unix, avand o arhitectura bazata pe cheie – valoare. Cheia nu poate sa depaseasca 255 de caractere iar valoarea este limitata la 1 MB. Toate informatiile sunt stocate pe servere in memoria RAM. Nu trebuia sa uitam ca viteza de citire in memoria virtuala este mult mai rapida. Spre exemplu, citirea are loc in RAM la 800 MB/s in vreme ce un HDD poate atinge doar viteze de pana la 100 MB/s. Exista si companii care prefera stocarea tuturor informatiilor in RAM si nu pe HDD din acest motiv. Evident, informatiile (backup) sunt stocate pe HDD-uri pentru ca ele sunt proceduri de stocare permanenta, dar cererile efective au loc in RAM.
Cum putem folosi Memcached – configurare
Pentru inceput avem nevoie de un server care sa aiba activat Memcache. Daca acest lucru este posibil PHP ne ofera o lista de functii pentru aceasta tehnologie. Totusi, avem nevoie de servere cu mult RAM care sa ne tina informatiile. Un mic guide pentru cei care folosesc Linux. Daca doriti sa folositi memoria RAM de pe un server cu Windows trebuie sa urmati pasii de mai jos :
1. Descarci memcached pentru Windows. (versiunea win32 binara)
2. Dezarhivezi si copiezi folderul unde vrei. Spre exemplu, poti folosi C:/memcached . Nu uita sa acorzi permisiuni de administrator daca folosesti Windows Vista / 7.
3. Instalezi aplicatia executand comanda c:\memcached\memcached.exe -d install in CMD
4. Deschizi serverul folosind comanda c:\memcached\memcached.exe -d start sau net start „memcached Server” in CMD
Ai acces la configuratia serverului Apache?
Daca da, poti verifica singur daca memcached e instalat.
1. Verifici daca folderul CALE\PHP\ext are fisierul php_memcache.dll , unde CALE reprezinta calea pana la serverul tau Apache.
2. Daca nu ai gasit fisierul, il poti descarca de aici, aici(pentru 5.2.*) sau aici (pentru 5.1.*).
3. Cauta fisierul php.ini. In el repereaza linia ce contine extension=php_memcache.dll. Daca linia exista, asigura-te ca nu are „;” (punct si virgula) la inceputul ei. Daca nu exista adaug-o la sfarsitul fisierului.
4. Restarteaza apache.
Cum folosim Memcached in PHP?
Am ajuns la partea interesanta. Pentru a folosi memcached in PHP ne vom folosi de cateva functii simple. Nu uitati sa consultati php.net pentru documentatia completa asupra Memcached din PHP.
<?php //versiunea OOP $memcache = new Memcache; $memcache->connect("localhost",11211); //ai putea inlocui localhost cu 127.0.0.1 daca nu merge echo "Versiunea serverului - ".$memcache->getVersion(); //setam cache - cheie worldit, valoare = $object, necomprimat, 10 secunde $object = array($memcache, 'cheie'=>TRUE); $memcache->set("worldit",$object,false,10); //extragem cache print_r($memcache->get('worldit')); //versiunea procedurala $memcache = memcache_connect('localhost',11211); echo "Versiunea serverului - ".memcache_get_version($memcache); memcache_set($memcache,$obj, 'worldit', $object, 0, 10); print_r(memcache_get($memcache,'worldit')); ?>
Exemplu efectiv
Mai jos aveti o functie clasica, de extragere a ultimelor noutati. De asemenea, urmatoarea functie incearca sa actualizeze noutatile (sa adauge una).
function get_news() { $result = mysql_query("SELECT * FROM news ORDER by id DESC LIMIT 10"); $data = array(); while($row = mysql_fetch_array($result)) $data[] = $row; return $data; } function add_news($title, $text) { mysql_query('INSERT INTO `news` (`title`,`text`) VALUES ("'.$title.'","'.$text.'")'); }
Daca analizam in perspectiva, aceasta functie va extrage practic ultimele noutati la fiecare accesare a paginii (principale sa zicem). Asta inseamna o gramada de query-uri inutile. Cu siguranta pagina principala nu se actualizeaza o data la o secunda ca sa se schimbe chiar atat de dramatic. De aceea, aici venim cu o mica solutie.
function get_news($update = FALSE) { global $memcache; //cautam in cache $data = $memcache->get('news'); if($data != NULL || $update == TRUE) { //nu am gasit in cache $result = mysql_query("SELECT * FROM news ORDER by id DESC LIMIT 10"); $data = array(); while($row = mysql_fetch_array($result)) $data[] = $row; //adaugam in cache $memcache->set('news', $data); } return $data; } function add_news($title, $text) { mysql_query('INSERT INTO `news` (`title`,`text`) VALUES ("'.$title.'","'.$text.'")'); get_news(TRUE); //actualizam cache }
Concluzie
Nu este deloc dificila implementarea Memcached in sistemul vostru, insa trebuie sa tratati cu mare grija si acest subiect sa nu ajungeti sa incarcati in cache chestii care nu isi au locul acolo. De obicei, se urmareste stocarea in cache a unor informatii ce se actualizeaza greu, sau mananca foarte multe cereri (timp).
Daca acest articol contine o greseala, selecteaza cuvintele sau fraza gresita si tasteaza combinatia de taste Shift + Enter sau apasa click aici pentru a o raporta. Multumim!
Foarte interesant. Frumos si util articolul. O sa testez si eu sa vad cum se comporta Memcached 🙂
Suporti memcache la tine? Daca da, incearca sa vii si cu niste rezultate aici. 🙂
Ai in cod „while($row = mysql_fetch_array($data))”. Cred ca e ” mysql_fetch_array($result)”. 🙂
Mersi Florian de observatie, am modificat. 🙂
Andrei am o intrebare la tine.
Am inteles ca functia „get_news” face update doar daca ii spunem noi sa faca, dar cum ii spunem de fapt? Ar functiona urmatorul scenariu?
In momentul in care din admin panel bag o stire noua imi reactualizez memcache iar cand utilizatoru da refresh vede si stirea noua.
Sau functioneaza pe ideea ca trebuie sa am un memcache per utilizator si sa fac update doar daca o valuare a unui cookie nu corespunde cu ce e pe server (sa zicem un time stamp)
Intreb pentru ca pe parte de web sunt mai slab. In afara de MySQL pur pt baze de date nu am folosit altceva.
Nu, ai inteles putin gresit.
Functia get_news() doar extrage ultimile noutati. Scenariu :
X,Y,Z cer aproape in acelasi timp noutatile, ele nefiind inca stocate in cache. X e primul si apeleaza functia get_news().
In momentul ala verifica daca e in cache – nu e, extrage din db, adauga in cache si ii returneaza lui X. Y face acelasi lucru, doar ca dispare – „nu e, extrage din db, adauga in cache”. Z la fel.
Actualizarea cache-ului are loc in functia add_news();
DA.
Cache-ul e pastrat in memoria RAM, care e disponibila pentru toti. 🙂
Ok mersi de lamuriri
Multumesc pentru tutorial .
E buna metoda memcached in cazul in care se fac 100-300 de request-uri pe secunda si serveru’ trebuie sa inregistreze numarul lor ? Apoi dupa un timp sa zicem 1-5 minute sa le bag in baza de date , le fac update (cele vechi din baza+ nr. din cache).
*linia 16 – in varianta procedurala $obj nu trebuie sters?
Nu chiar. Memcached, prin natura sa e o alternativa NoSQL ce stocheaza datele in RAM pentru aplicatii cu o intensitate mare de citire. O alternativa care se lauda ca ar rezolva ambele probleme e dbShards (read & write intensive). Pe partea de write intensive nu am testat multe asa ca nu prea ma pot exprima in totalitate. 🙂
[…] recomandă să folosim module de caching precum MemCached sau sisteme de template-uri care suportă cache precum […]
Pentru Linux nu este ?:))