Rašydamas straipsnį “Tinklalapių augimas – ką daryti, jei jiems pasidaro ankštoka?” ne kartą vartojau žodį kešas (angl. cache). Lietuviškai tai būtų podėlis, bet straipsnis ne apie teisingus lietuviškus terminus.

Jei kreipsimės į anglišką Wikipedia, tai rasime ilgą ir gražų straipsnį apie cache. Lietuviškai ir trumpai būtų galima reziumuoti taip (faktiškai pirmas sakinys): tai duomenų rinkinys, dubliuojantis reikšmes, išsaugotas kitur arba apskaičiuotas anksčiau. Taigi, kur jis naudojamas internete? O pasirodo visur.

Kešas kliento pusėje

Su kešu mes susiduriame nuo pat pirmo WWW panaudojimo momento. Kur? Ogi naršyklėje (angl. browser). Pagal nutylėjimą visos populiariausios naršyklės (Microsoft Internet Explorer, Mozilla šeimos atstovai, Opera) parsisiųsdamos tinklalapius viską saugo Jūsų kietajame diske (HTML kodą, paveiksliukus, CSS, JavaScript, Flash, ar ką jus ten naudojate). O kai vyksta antra užklausa tuo pačiu adresu naršyklė patikrina, ar nėra tokio objekto jūsų kietajame diske ir jei yra, specialia užklausa patikrina ar ne laikas atnaujinti šio objekto. Čia viskas remiasi HTTP specifikacija, todėl, jei manysime, kad pasaulis yra idealus, šia technologija galima pasitikėti.

Kaip pavyzdį panagrinėkime Pixel.lt fono paveiksliuko failą: bgimg3.jpg, jei jūs pirmą kartą apsilankote Pixel.lt tinklalapyje, tai HTTP užklausa atrodo taip:

GET /new/wp-content/themes/pixel/images/bgimg3.jpg HTTP/1.1
Host: pixel.lt
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7
[o čia dar daug daug šaunios informacijos]

O atsakymas toks:

HTTP/1.1 200 OK
Date: Mon, 01 Oct 2007 19:36:43 GMT
Server: Apache
Last-Modified: Thu, 30 Aug 2007 20:27:13 GMT
Etag: "eb1065-898d-88118a40"
Accept-Ranges: bytes
Content-Length: 35213
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: image/jpeg
[o čia jau seka pačio paveiksliuko duomenys]

Čia labai svarbu atkreipti dėmesį į dvi HTTP antraštes: Last-Modified ir Etag. Pirmoji nusako, kada paskutinį kartą buvo keistas šis failas, antroji yra informacija apie užklausą, galima spręsti, ar kešas yra geras. Būtent jos leidžia spręsti, kad objektą galima kešuoti. Todėl, sekanti užklausa bus:

GET /new/wp-content/themes/pixel/images/bgimg3.jpg HTTP/1.1
Host: pixel.lt
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7
If-Modified-Since: Thu, 30 Aug 2007 20:27:13 GMT
If-None-Match: "eb1065-898d-88118a40"
[o čia vėl dar daug daug šaunios informacijos]

Užklausoje atsirado dvi naujos antraštės: If-Modified-Since ir If-None-Match. Pirmoji pasako serveriui, “kokio šviežumo” failus turi klientas, antroji - objekto žymė, kurią sutikrinus serveris sprendžia, ar geri kliento kešo failai (t.y. naršyklės kešo failai).

Atsakymas gali būti dvejopas, remiantis If-Modified-Since ir If-None-Match (viską sprendžia serveris) - arba, jei turinys keše yra geras:

HTTP/1.1 304 Not Modified
Server: Apache
Date: Mon, 01 Oct 2007 19:36:44 GMT
[o čia jau seka kitos HTTP antraštės, bet nėra jokio turinio]

arba, jei kešas yra blogas siunčiamos standartinės antraštės ir turinys:

HTTP/1.1 200 OK
Date: Mon, 01 Oct 2007 19:36:43 GMT
Server: Apache
Last-Modified: Thu, 30 Aug 2007 20:27:13 GMT
Etag: "eb1065-898d-88118a40"
Accept-Ranges: bytes
Content-Length: 35213
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: image/jpeg
[o čia jau seka pačio paveiksliuko duomenys]

Taip veikia pats paprasčiausias kešas, kurį turi beveik visos naršyklės. Programuotojai jį gali dalinai įtakoti, bet niekas niekada negali užtikrinti, kad kliento pusėje (naršyklėje) viskas veiks gerai, ir tas kešavimas bus bei veiks teisingai. Juk tai, kas yra kliento pusėje (naršyklė) visada galima pakeisti, perkonfigūruoti ar perprogramuoti, kad jis nenaudotų šio kešo ar viską imtų iš jo.

Ar mums reikia kešo, ar reikia jį naudoti? Taip, taip, taip ir dar kartą taip! Kam vartotojui kaskart siųstis duomenis, jai jie nėra atnaujinti, o jis juos jau turi? Iš kešo viskas kraunama žymiai greičiau, be to, yra taupomas jūsų ir vartotojo kanalo pralaidumas. Pagal nutylėjimą jis naudojamas visiems statiniams failams (t. y. jų paskutinio modifikavimo žymė iš failų sistemos) Apache, Lighttpd, NGINX ir IIS HTTP serveriuose (kitų nesu tikrinęs). Deja, daugelis PHP, ASP, JSP, Ruby, Python skriptų šios galimybės neišnaudoja. Norint ją išnaudoti reikia rašyti papildomą programinį kodą, o besikeičiant verslo logikai šią dalį reikia nuolat atnaujinti.

Kešas serverio pusėje

Dar vienas kešas, kurio niekas nedokumentavo ir nekūrė jokių standartų. Yra kelios paplitusios technologijos, kurias aš pasistengsiu apžvelgti.

Viso sugeneruoto puslapio kešavimas

Dažniausiai tinklalapiai neturi daug dinaminės informacijos savo puslapiuose, nekreipiant dėmesio į tai, kad beveik visur yra įdiegtos turinio valdymo sistemos. Turinys yra atnaujinamas žymiai rečiau nei jį peržiūri vartotojai. Toks sugeneruotas puslapis saugomas serverio kietajame diske arba serverio atmintyje, arba duomenų bazėje. Kiekvienas iš šių būdų turi savų pliusų ir minusų, todėl juos reikia rinktis pagal galimybes. Toks kešavimo būdas gali leisti jums išnaudoti Last-Modified/If-Modified-Since ir Etag/If-None-Match HTTP antraštes. Jis tinka jei tinklalapyje nėra prisijungimo formų, registracijų, balsavimų ar panašių interaktyvių dalykų, arba reikia atsižvelgti į tai kuriant tokią kešavimo sistemą.

Kuriant tokį kešavimą, pirmiausia reikia apmąstyti – ar to tikrai reikia ir ar tai įmanoma? Ar jūs tikrai viską padarėte ir kitos išeities nėra? Ar tikrai puslapio generavimo laikas yra toks tragiškas? Kaip jūs valdysite kešo atnaujinimą? Ar jūs įsitikinę, kad turima techninė įranga tai atlaikys (kietas diskas spės skaityti, rašyti, atnaujinti, užteks atminties, ar yra resursų duomenų bazėje)? Ar tinkama tam failų sistema? Ar kešo saugojimo struktūra yra gera (atsiminkite, kad jei viename kataloge yra tūkstančiai skirtingų failų, tai failo paieška ženkliai sulėtėja)? Ar neįvyks klaidingas kešo failų perrašymas esant dviems vienodoms užklausoms?

Jei pasirenkate sprendimą su saugojimu į duomenų bazę, tai kas bus jeigu bazė neveiks? Kaip tai įtakos duomenų bazės serverį? Gal reikia atskiro serverio tam? Koks bus lentelių tipas (jei tai aktualu)? Galbūt apsimokėtų naudoti ne client-server tipo bazę? Kaip jūs valdysite kešo atnaujinimą?

Jei pasirenkate sprendimą su saugojimu į serverio atmintį ar užteks atminties kitiems procesams? O ar jūs galite, tai sau leisti (pvz., virtualiuose serveriuose už tai gali „nubausti“ ir nebūtinai serverio administracija)? Kaip jūs valdysite kešo atnaujinimą?

Pavyzdžiui, jeigu pixel.lt neturėtų komentarų, įvertinimų, skaitliuko (kiek kartų perskaitytas straipsnis), tai visą šią svetainę galima būtų išsaugoti kaip statinius HTML failus ir pergeneruoti tik tada, kai atsiranda naujas straipsnis (paiešką organizuoti kaip atskirą PHP skriptą).

Ar mums reikia šio kešo, ar reikia jį naudoti? Taip, jei neturime jokios kitos išeities ir ieškome greito ir pigaus sprendimo. Be to, toks būdas leidžia mums išnaudoti Last-Modified/If-Modified-Since ir Etag/If-None-Match HTTP antraštes, todėl taip sutaupome serverio ir tinklo resursų.

Puslapio dalių kešavimas

Kadangi vis daugiau puslapių naudoja registracijas, balsavimus ar kitus dalykus (informacijos blokus, kurie naudojami daugelyje puslapių, palyginti retai atnaujinami, bet jų generavimui reikia daug resursų), o puslapių generavimas pradeda reikalauti dėl to daugiau resursų, tokiu atveju kešuojamas ne visas puslapis, o tik jo dalis.

Čia jau neverta mąstyti apie kešavimą į failus, nors kartais užtenka ir jų. Kešuojama būtent ta dalis, kuri yra palyginti rečiausiai atnaujinama ir/ar reikalauja daugiausia resursų generavimui.

Pavyzdžiui, Pixel.lt turi bloką Kategorijos/Gairės, kuris kartojasi per visus Pixel.lt puslapius. Jo sugeneravimui reikia mažiausiai 2 užklausų su WHERE, JOIN ir duomenų agregacija (o tai reikalauja resursų). Jis generuojamas kaskart, kai vartotojai užklausia puslapį, kaskart atliekamos užklausos. O kodėl jo po pirmos generacijos neįmetus į kešą, ir sekantį kartą atnaujinti tik tada, kai atsiras naujas straipsnis, kategorija ar gairė?

Galima kešuoti ne sugeneruotas puslapio dalis, o duomenis (masyvus, objektus) skirtus šiems puslapiams formuoti. Keša saugoti vėl įprastoje mums vietoje: diske, atmintyje, duomenų bazėje.

Pavyzdžiui, Pixel.lt pirmasis puslapis yra sudarytas iš straipsnių sąrašo, prie kiekvieno straipsnio (pavadinimas, sutrumpinimas, data) yra dar informacija apie autorių, kategorija, gairės. Viskas imama iš duomenų bazės, o kelių kategorijų ir gairių per vieną užklausą ne visada ir sugrėbsi. Ši informacija nėra nuolat atnaujinama, palyginus su komentarų skaičiumi, peržiūrų skaičių. Todėl informaciją šiam sąrašui formuoti galbūt būtų tikslinga išsaugoti kaip jau suformuotą masyvą ir naudoti jį.

Pastaba

Dalį visų šių kešavimų gali atlikti ir duomenų bazė, naudojant užklausų kešavimo mechanizmus. Pavyzdžiui MySQL turi Query Cache. Bet kešavimą duomenų bazės lygyje valdo pati duomenų bazė, o ne programuotojas/sistema, kas turi tiek savų pliusų, tiek ir minusų. Apie kešavimą duomenų bazės lygyje siūlau pastudijuoti savarankiškai, tai labai svarbu, jei jūs projektuojat sistemą su MySQL duomenų baze..

Ar mums reikia šio kešo, ar reikia jį naudoti? Taip, jai mes turime didžiulį lankomumą, o resursai mums neleidžia išspręsti iškilusių problemų kitų būdu. Tik pagalvokit, jei jums reikia per vieną sekundę parodyti 100 puslapių, kuriuose yra vienas ir tas pats blokas, reikalaujantis 5-10 užklausų į duomenų bazė ir jos užtrunka ilgai (gal kiekviena ir neilgai, bet sudėjus kartu bei padauginus iš šimto norisi verkti) ar neapsimoka tą blokelį kur nors sugeneruotą atmintyje palaikyti 3-5 sekundės, taip leisti kitoms užklausoms atlikti savo darbą, o vėliau vėl atnaujinti? Juk idealių sąlygų nebūna – visada atsiras ta rakštis, kuri privers jus mąstyti nestandartiškai.

Kešavimo problemos/klausimai yra beveik tie patys, kaip ir kešuojant visą sugeneruotą puslapį. Tik dar reikia atsižvelgti į tai: ar dažnai šis blokas atnaujinamas, ar daug laiko užims šios dalies kešavimo strategijos kūrimas ir įgyvendinimas, ar nepažeisime verslo logikos.

Kešavimas su proxy serveriu

Dar vienas būdas, labai panašus į aukščiau aprašytą „Viso puslapio kešavimą“. Tik šiuo atveju nieko nereikia keisti Jūsų sukurtoje sistemoje (na gerai, reikės, bet viskas priklauso nuo turimos sistemos ir tos programinės įrangos, kurią jūs naudosite). Tam naudojama „reverse proxy“ programinė įranga. Jis fiziškai yra prieš jūsų HTTP serverį (o gali būti net kelios), visos klientų užklausos keliauja į tokį proxy, o proxy jau sprendžia ar siųsti šią užklausą serveriui, ar jis pats gali susidoroti (pagal šią užklausą jis turi turinį, kurį gali pateikti klientui). Dažniausiai tokia programinė įranga kešuoja viską, ką jai jūs leidžiate: paveiksliukus, JavaScript, CSS, HTML puslapius, faktiškai viską, kas keliauja per HTTP nuo jūsų serverio iki klientų. Kešavimo trukmė ar kešo atnaujinimas priklauso vėlgi nuo programinės įrangos, jos konfigūracijos ir jūsų sistemos.

Kadangi šio kešavimo galimybes, priešingai nei anksčiau aprašytų, aš esu studijavęs mažiausiai bei sukūriau tik vieną veikiantį modelį su Squid ir Apache aš čia sustosiu. Pažymėsiu tik, kad čia jums tikrai prireiks papildomų serverių ir gero administratoriaus. Be to, teks išstudijuoti visą vartotojo vadovą apie naudojamą programinę įrangą kešavimo serveriui.

Ar jis mums reikalingas? Na, čia jau jums spręsti.

Trečios šalies duomenų kešavimas

Dažnai tinklalapiuose tenka rodyti informaciją iš trečių šaltinių.

Informacija iš įvairių šaltinių, dažniausiai XML formate, gaunama iš trečios šalies, „parsinama“ į mums reikalingą pavidalą ir parodoma mūsų puslapyje. Kodėl reikia ir čia kešuoti? Jeigu trečios šalies serveris staiga nustos veikti (nulūžo, klaida XML, nutrūko ryšys), kad jūsų tinklalapis neišmestų klaidų ir parodytų kažkokią informaciją. Ypač aktualu tiems, kas rodo svetimus RSS srautus, prekių katalogus tiesiai iš tiekėjo sandėlio (būna labai malonu pardavėjo kainininkuose matyti pranešimus apie klaidas tiekėjo serveriuose realiajame laike). Be to, kiekvieną kartą lakstyti pas tiekėją dėl tos pačios informacijos nėra sveika (savaime aiškų, jei yra galimybės nelakstyti).

Šiuo kešavimu jums teks pasirūpinti patiems, nebent jūs naudojate programinę įrangą, kuri tai jau sugeba. Taip pat teks pasirūpinti kada reikėtų atnaujinti kešą.

Kešavimas „kažkur“ ir „kažkaip“

Dar yra toks keistokas kešavimas, kurio niekas niekada negalės suvaldyti. Tai kešavimas „kažkaip“ „kažkur“. Tarp jūsų serverio (kur yra jūsų tinklalapis) ir naršyklės būna nuo vieno iki keliasdešimties kompiuterių. Jūs gyvenime nesužinosite jų paskirties. Pavyzdžiui, vietinis „kaimo“ tiekėjas gali įdiegti kešuojantį proxy serverį norėdamas sumažinti srautą; arba naršyklė „apsivalgyti“ kešo ir rodyti nesamones (bent Microsoft Internet Explorer 6 sirgdavo šia liga). Būna, kad talpinimo (angl. hosting) kompanijos prieš serverį pakuria kešuojantį proxy (kurį aprašiau aukščiau) serverį, kurį jums valdyti bus sunku arba neįmanoma, o jis kešuos ne tik statinį turinį pagal tik jam vienam žinomas taisykles, bet ir tai, ką jūs sugeneruojate su PHP/ASP/ar ką jus ten naudojate, siųsdami bet kokias antraštes ir pridedami bet ką į adreso eilutę. Toks nesaikingas kešavimas gali sugadinti jums keletą nervų ląstelių ir yra visiškai nereikalingas.

Vietoj pabaigos

Na, štai toks tas kešavimas. Dėl to ar reikia, ar ne kešuoti nuolat vyksta „šventas“ karas. Vieni kalba, kad reikia. Kiti kalba, kad nereikia. Todėl visi sprendžia patys, pagal esamą situaciją. Svarbiausia nepamiršti apie tai, kad klientai/naršyklės kešuoja ir kad kažkur gali buti kažkas kas irgi gali kešuoti (nors tokius atvejus aš sutinku vis rečiau). Atminkite, kad gerai suprojektuotas kešavimas dar niekam nepakenkė.

Kešavimui naudojamos programinės įrangos sąrašas

Na, jis nebus pilnas, jūs būtinai rasite internete dar ir dar, bet paminėsiu populiariausius.

Kešavimui atmintyje naudojama programinė įranga:

Memcached - vienas populiariausių produktų, daugelis programavimo kalbų turi galimybę dirbti su šia programine įranga.

PHP gali naudoti tokį plėtinį kaip APC, kartais naudojamas shmop.

„Reverse proxy“ galimybes turinti programinė įranga:

Apache HTTP Server su proxy ir cache moduliais.

Squid, Lighttpd, NGINX

Panašūs straipsniai


“Kešas - kas tai, ir ar mums to reikia?” komentarų: 3

  1. ziogas

    Labai geras straipsnis, senokai jau tokį lietuvškai skaičiau :)

  2. kusemmekaars

    Geras straipsnis

  3. Pixel.lt ir “Microsoft Lietuva” konkurso nugalėtojai » Pixel.lt

    […] kategorijoje Sauliui nusileido ir antrąją vietą užėmė Sergej Kurakin su straipsniu “Kešas - kas tai, ir ar mums to reikia?” Na, o trečiąją vietą programavimo kategorijoje laimėjo Žilvinas Sadauskas su […]

Rašyti komentarą

Jūs privalote prisijungti jeigu norite rašyti komentarą.