Ovih dana puštamo u opticaj novi Kreni!. Kad kažem “novi”, na žalost, ne mislim na novi dizajn. Šta više, sve promene koje su izvršene, desile su se “pod haubom” i neće biti vidljive na prvi pogled.
U protekla dva meseca provedeno je mnogo vremena analizirajući rad sajta kako kroz source code (PHP) tako i kroz bazu podataka (MySQL). Kako je tokom ove dve godine postojanja sajt stalno proširivan novim servisima a akumulirani podaci u bazi su stalno rasli, bilo je pitanje vremena kada će sve postati jako klimavo po pitanju stabilnosti baze i brzine odaziva celog sistema.
PHP
Prvo od čega smo krenuli jeste “češljanje” oko 90.000 linija PHP koda. Trebalo je izbaciti sav nepotreban kód koji je samo stajao tamo, ubrzati najčešće korišćene funkcije i optimizovati upotrebu memorije. S obzirom da Kreni! nije zasnovan ni na jednom gotovom open source rešenju nismo mogli samo update-ovati software i nadati se poboljšanju performansi. Imajući u vidu buduća proširenja sajta, napisane su mnoge biblioteke i klase koje su poslužile kao osnova za pretvaranje svih servisa u “modularni sistem”. Ovako su servisi bili zasnovani na istom funkcionalnom temelju koji im je omogućio da razmenjuju zajedničke podatke bez potrebe za novim pristupima bazi. Modularnost je pogotovu bila značajna za rad bot-ova koji su skidali podatke sa neta ili osvežavali ove zajedničke podatke kroz sistem međusobne “razmene”.
Ova razmena podataka je realizovana sa memcache-om. Iako je sistem i do sada koristio keširanje podataka (na disku) tek je sa upotrebom memcache-a došlo do ubrzanja performansi.
MySQL
Ono što je sledilo jeste optimizacija baze podataka. Kako u strukturi tabela, načinu indeksiranja podataka unutar tabela tako i samih query-a koji izvlače podatke. Koliko pravilno indeksiranje tabela ubrzava iščitavanje podataka nije potrebno da govorimo, ali postoje situacije kada MySQL ne može da izađe na kraj sa količinom podataka ma kako dobro izvršili njihovo indeksiranje.
Konkretno mislim na FULLTEXT indeksiranje koje je korišćeno za pretraživanje naslova i blog članaka. Kada pretražujete 2.500.000 naslova (oko 2GB podataka) MySQL počinje da koči u odazivu. Pogotovu ako se pretražuje po nekoliko različitih ključnih reči za 20 online korisnika koji bi da ove rezultate pretrage dodatno isfiltriraju po kriterijumima kao što su: izvor, jezik, popularnost i/ili postojanje propratne slike ili sličnih naslova. Odaziv je sa nekoliko milisekundi rastao tokom zadnjih meseci na nekoliko stotina milisekundi pa čak i nekoliko sekundi što je postalo nedopustivo za dalji opstanak. Da stvar bude još gora, u pojedinim situacijama MySQL se nije mogao izvući iz navale zahteva za novim pretragama što je rezultovalo blokiranjem sistema i izbacivanjem poruke “Sajt je trenutno nedostupan!“.
Prva pomoć pružena je u proširenju memorije servera (sa 2GB na 4GB). Ovo je dosta pomoglo jer su indeksi bili keširani u memoriji ali se MySQL i dalje zaglavljivao kada je pretragu koristilo nekoliko korisnika odjednom.
Bilo je vreme pronaći novi metod pretrage. Iako još nismo bili spremni da odustanemo od MySQL-a za skladištenje, razmatrane su pojedine ne-relacione baze podataka kao što su Cassandra, BigTable i slične. A onda smo se setili jednog rešenja koji vrlo uspešno koriste mnogi poznati sajtovi: Sphinx.
Prvi testovi pokazali su kako je ovaj metod pretrage (za gore pomenutu količinu podataka) itekako zgodan za upotrebu jer je odaziv bio čak i do 100x brži (u jednokorisničkom okruženju) od FULLTEXT pretrage. Bilo je potrebno samo adekvatno odrediti vreme reindeksiranja sadržaja kako bi korisnici dobijali što svežije naslove. Sphinx je zbog lakog korišćenja i brže pretrage upotrebljen i u pojedinim situacijama gde nije bila korišćena FULLTEXT pretraga ali je bilo potrebno grupisati podatke po raznim GROUP BY filterima. Uz dodatno keširanje memcache-om servis Naslovi je ovako postao sasvim prijatan za korišćenje.
Kuda dalje…?
Ovime se priča o optimizaciji ne završava. Sledi dodatno osvežavanje hardware-a (SSD diskovi?), odvajanje Web od DB servera, prebacivanje statičkog sadržaja (slike, js i css datoteke) na poseban CDN server itd, itd.
Let the fun begin!