ugrás a tartalomhoz

Cache-elés folyamata

Max Logan · 2008. Szep. 22. (H), 01.46
Tegyül fel, hogy van egy blogunk, ami megjeleníti a kezdőlapon az utolsó 10 bejegyzést. Ezt mi szeretnénk cache-elni, hogy ne kelljen minden oldaltöltésnél lekérni az utolsó 10 bejegyzés adatait (cím, dátum, szerző, címkék, stb.) az adatbázisból.

Folyamat: Ellenőrizzük, hogy a cache érvényes-e még. Ha nem, akkor generáljuk, ha igen beolvassuk. A cache akkor érvénytelen, ha nem létezik, valamint ha létezik és a készítése óta van már újabb bejegyzés. Akkor érvényes, ha van cache fájl és a készítése óta nem született újabb bejegyzés.

Azt egy, az adatbázisban tárolt flag alapján döntük el, hogy van-e újabb bejegyzés. Vagy itt kérjük le az utolsó bejegyzés ID-ját és azt csapjuk hozzá a cache file nevéhez? (előbbi nekem szimpatikusabb)

És itt jön a dilemmám: a cache-elést hol valósítsam meg?

A model-ben? Szedjem össze a 10 bejegyzés adatát, írjam ki egy file-ba (pl. serializált tömbként), majd kiírásnál olvassam be és adjam át a view-nak?

A controller-ben? Kérjem le a flag-et, hogy van-e újabb bejegyzés és ennek függvényében hozzam létre a teljes html kimenetet és azt cache-eljem?
 
1

Az érvényesség ellenőrzését ...

Max Logan · 2008. Szep. 22. (H), 01.57
... még bonyolítani kell. Ha a bejegyzések listájánál ki van írva, hogy hány komment érkezett a bejegyzéshez, akkor minden esetben érvénytelen a cache, ha az utolsó 10 post valamelyikéhez új komment érkezett.
2

szituációtól függ

Hodicska Gergely · 2008. Szep. 22. (H), 02.23
Erre a kérdésre kb. rengeteg féle megoldás adható, 1 féle jó megoldás talán nincs is, plusz nagyon függ a körülményektől is.

Egy féle döntő szempont lehet, hogy feltétlenül akarod-e egyből érvényre juttatni a változásokat. Ha pl. egy nem épp kommentelő ember jön, akkor nagy terhelés esetén simán alkalmazzák, hogy a cache fix ideig él. Ha épp kommentelt valaki, akkor neki érdemes az aktuális adatot mutatni, különben csodálkozni fog.

Attól is függ a dolog, hogy pl. hány webszervered van. Ha csak egy akkor pl. simán tárolhatsz opcode cache-ben (általában mindegyikben van ilyen funkció és gyorsabb, mint a memcache, és hát opcode cahce-ed biztosan van, ha már egyszer számít a teljesítmény) egy cache verzió számot. Mindig ezt használod, amikor lekéred cacheből a cikklistát. Általában van atomi increase is, szóval a kölcsönös kizárással sem kell nagyon bajlódni.

MySQL-ből is lehet Memcache-t piszkáni, így akár már ott is invalidálhatod a cache-ed mondjuk triggerből.

A megvalósítás helye tényleg érdekes lehet. Ha a modellen belül van, akkor annyi hátránya van, hogy a modellt használótól a cache-elés ténye el van rejtve. Ha a kontrollerben van, akkor meg mindig minden felhasználási helyen bajlódni kell a cache-eléssel.

Én annó csináltam olyan alap osztályt, ami automatikusan megvalósította a cache-elést (__call-on voltak átvazetve a metódusok, paraméterek alapján számolt md5 volt a kulcs), és minden leszármazott osztály konstruktorában, vagy a függvény hívásakor extra paraméterekkel (reflection API-val jól lehetett ezeket kezelni) lehetett a cache-elést vezérelni. Mivel így kvázi egy mini framework volt az oszátlyok alatt, így mindig tudhatta a fejlesztő, hogy a metódusok cache-elve lehetnek, és hogy egy fix helyen kell ennek utánanéznie.

Egy másik jópofa megoldás lehet erre a Decorator pattern (csak Tolminak: Díszitő minta :D) használata. Cisnálsz egy oszátályt, ami mondjuk konstruktorban megkapja a cache-eléssel kapcsolatos paraméterekt, meg a model osztályt. Ezen hívod meg a kérdéses megtódust, és a __call-ban ellenőrzöd a metódus paraméterei alapján, hogy megvan-e a cache-ben a stuff, ha nem, akkor a modellen meghívod a metódust, cache-eled, és így adod vissza. Így relatíve kevés a kliens kódban az "overhead", viszont látszik, hogy az adat cache-elve van.


Üdv,
Felhő
4

Egyke minta (a.k.a. singleton pattern)

tolmi · 2008. Szep. 22. (H), 09.59
csak Tolminak: Díszitő minta :D

Na elmész te a ... :D

Csak hogy mindenki értse miért szól ez nekem: Kifejezett nemtetszésemet nyilvánítottam ki a magyar nyelvű Programtervezési Minták könyv gyászos minősége miatt. Azok az újkazinczik akik ezt művelték, nem lesznek a barátaim.

Mindenféle technológiai tisztelet nélkül műfodítást végezni egy igen nagyrabecsült (legalábbis eredeti angol nyelven) könyvön minimum 10 év börtönt érdemelne az ilyen.

Szóltam. Uff!
3

Depending caches

janoszen · 2008. Szep. 22. (H), 06.46
Gondolkoztam már ezen a témán és odáig jutottam, hogy föl kéne építeni egy olyan struktúrát, amely megmondja, hogy melyik cache (leginkább összetett cache, tehát több elemi rekordból összeálló) bejegyzés melyik rekordtól függ. És itt akadtam el a dologgal, ugyanis ha új bejegyzés születik, akkor az összes oldal invalidálódik mert mindenhol shiftelődnek eggyel a tartalmak, stb. Ergó nem jutottam előbbre. :)
5

Hol tároldójon a cache

Max Logan · 2008. Szep. 23. (K), 16.46
Én eddig azt a logikát követtem, hogy a cache-ek file-okban tárolódnak. Bizonyos esetekben ez a gondolatmenet helytálló (CSS és JS összefűzött cache-ek), de pl. a fent említett bejegyzéslista cache esetén felmerül, hogy file-ba tároljam vagy az adatbázisban legyen egy cache tábla, amibe mentem a különböző cache-eket. Teljesítmény szempontjából melyik a jobb megoldás?
6

Váratlan válasz

tolmi · 2008. Szep. 23. (K), 19.13
A memcache :)

Nade viccet félre. Szerintem attól függ. Megfelelő adatbáziskonfig mellett (pl. mysql memóriatáble) sokkal gyorsabb lesz adatbázissal.
7

Egy infót kifelejtettem ...

Max Logan · 2008. Szep. 23. (K), 19.38
... mégpedig azt, hogy osztott hosting-ra fejlesztve. Tehát bérelt tárhelyen futtatva a kódot, nem saját szerveren.
8

Hát innen számítva járhatsz

tolmi · 2008. Szep. 23. (K), 23.11
Hát innen számítva járhatsz nagyon rosszul és nagyon jól is az adatbázissal. A filerendszer egy általános közepesen rossz megoldás lesz.

Ajánlom hogy valahogy inkább memóriába zsúfold bele valahogy (shmem?)
9

fájl cache lehet jobb a mysqlnél

Hodicska Gergely · 2008. Szep. 23. (K), 23.17
Megfelelő adatbáziskonfig mellett (pl. mysql memóriatáble) sokkal gyorsabb lesz adatbázissal.
Nem egészen. MySQL esetén is a leggyorsabb akkor lesz, ha a query cacheből jön, ennél már lassabb a memory táblában való tárolás. Ha viszont nem túl sok adatról van szó, akkor query cachenél is simán gyorsabb lehet fájlban való cache-elés, mert jó esetben ezt memóriából fogja az OS kiszolgálni.

mégpedig azt, hogy osztott hosting-ra fejlesztve. Tehát bérelt tárhelyen futtatva a kódot, nem saját szerveren.
Érdemes lehet még azt is megnézned, hogy van-e valamilyen opcode cahce, ezekben is szokott lenni memóriában való tárolási lehetőség. Kérdés persze, hogy a szolgáltató engedélyezi-e, ha igen, akkor ez lesz a leggyorsabb.

Ha van opcode cahce, de a memóriában való tárolást végző metódusok le vannak tiltva, még akkor is el tudok képzelni egy olyan perverzebb dolgot, hogy egy PHP tömböt írsz ki egy PHP fájlba, és ezt include-olod, amikor szükség van az adatra, és így végül mégiscsak cache-elve lesz, de ezt már ki kéne mérni, hogy nyer-e vele az ember.

Ha nem memcache-t használsz, akkor viszont neked kell majd takarítani magad után a cache-t.


Üdv,
Felhő
10

Van opcode cache ...

Max Logan · 2008. Szep. 23. (K), 23.53
... méghozá ionCube. Egyelőre úgy néz ki, hogy az ionCube Encodert fogom megvenni (jóval olcsóbb, mint a Zend Guard; esetleg valami ami a ZG mellett szó?).

Az alatt pontosan mit értünk, hogy nekem kell eltakarítani a cache-t?
11

szezon vs fazon ;)

Hodicska Gergely · 2008. Szep. 24. (Sze), 00.09
Az ionCube Encoder az nem opcode cahce. Volt amúgy az ionCube-nak opcode cache-e is, de azt már elég régóta nem fejlesztik. Mostanában amik vannak: APC, Xcache, eaccelerator. Előbbi elvileg hvatalosan része lesz a PHP6-nak.

Az alatt pontosan mit értünk, hogy nekem kell eltakarítani a cache-t?
A memcache-nek meg van az az előnye, hogy jóformán csak dobálod bele a dolgokat, és nem kell takarítani, az LRU megoldja, hogy ha elfogyna a neki szánt memória. Ha DB-be írsz, fájlba teszel le dolgokat, akkor ezek nem fognak maguktól eltűnni, ezért neked kell megoldani a takarításukat.


Üdv,
Felhő
12

APC van

Max Logan · 2008. Szep. 24. (Sze), 01.25
APC van a tárhelyen (3.0.16). Most néztem php.net-en (és ki is próbáltam a tárhelyen), hogy lényegében APC használata annyi, hogy beteszek dolgokat és kiveszek dolgokat. Beállítom a TTL-t, amikor beteszek valamit és a GC majd eltakarítja. Azaz, nem nekem kell bajlódom a tárolással, nekem csak be kell dobálnom az adatokat, meg kiolvasni amikor kell.

Visszatérve az ionCube-ra. Az ionCube és a ZendGuard azt a bytekódot állítja elő, amit a PHP futásidőben, csak még titkosít is rajta? Vagy tévedek (ez könnyen előfurdulhat, ezért is kérdezek)?
14

Szolgáltatló?

tolmi · 2008. Szep. 24. (Sze), 09.43
Elárulod melyik szolgáltató az? Ritkán látni olyan hogy APC van engedélyezve shared hostingnál.
16

Re: szolgáltató

Max Logan · 2008. Szep. 24. (Sze), 10.20
UltraNet-nél (ultranet.hu) van tárhelyen és hozzájuk vittem az ügyfeleket az utóbbi időben akinek honlapot csinálnok/csináltam. A Silihost-on gondolkodtam, hogy majdan oda áttelepülök a jövőbeli project-ekkel, ha kell nemzetközi sávszél is (UltraNet-nél voltak gondok anno nemzetközi sávszéllel, bár könnyen meglehet, hogy ez nem az ő hibájuk volt.)
18

APC cache_by_default

Max Logan · 2008. Szep. 24. (Sze), 12.45
Nos, a szerveren engedélyeztem (egy test könytárban), hogy automatikusan cache-elje a file-okat (a meghívott PHP-k be is kerülnek a cache-be, a stat szépen mutatja).

A kérdésem már csak az, hogy ha én ionCube-bal titkosítom a kódomat (pl. mert egy fejlesztett rendszert termékként szeretnék értékesíteni), akkor is működni fog az APC auto cache része?
13

két apró

winston · 2008. Szep. 24. (Sze), 09.31
két apró megjegyzés/vélemény:

én csináltam ilyen "array cache" jellegű dolgot, vagyishogy tömböt írtam ki php fileba. elég sokat megspóroltam vele, főleg számításigényes dolgoknál, illetve az adatbázisírásterhelés egy részét is kiváltottam vele (session adatok tárolása. nem a legjobb megoldás, de bizonyos helyzetekben célszerű volt). nyilván a legjobb eredményt akkor éred el, hogy ha memdrive-ot használsz. fontos figyelni a műveletek atomiságára, hogy nehogy inkonzisztens állapotba kerüljön a file. ez pl. egy session-jellegű használat során nem kritikus, lévén általában egy ember használja, nem lesz ütközés, de általánosabban használt adat esetén erre erősen figyelni kell

a másik annyi, hogy a memcached és hasonló alkalmazások hibája, hogy ha nem kap fastcgi-al teljesen saját instance-ot (de talán akkor is...) vagy saját virtuális gépet, akkor a szerveren található szájtok memcachei nincsenek elkülönítve. ez erőteljes ok lehet arra, hogy a szolgáltató ne engedje a használatát (nem vagyok rendszergazda, csak memcached alatt találkoztam ezzel, de gondolom a hasonlóságukból ítélve többi megoldás is ilyenformán reagál)

szép napot,
w.
19

Auth

janoszen · 2008. Szep. 24. (Sze), 14.43
Ld. a memcached leírásában a milyen autentikációt támogat kérdésre a választ: nincs autentikáció. Ezen egyébként az iptables owner modulja segíthet az output chainen.
15

Kontra

tolmi · 2008. Szep. 24. (Sze), 09.45
MySQL esetén is a leggyorsabb akkor lesz, ha a query cacheből jön, ennél már lassabb a memory táblában való tárolás.

A query cache ott lesz akkor is ha MEMORY engine-t használsz. Ráadásul a query cache-be nem tudsz közvetlen írni. Tehát a mem táblával jobban járhatsz, mint mondjuk MyISAM-mal, mert ha nem query cache-ből jön a válasz, akkor az engine-nek kell válaszolni és meggyőződésem hogy a MEMORY engine sokkal gyorsabb mint bármelyik diszk alapú engine. Persze ha nem férsz el a memóriában, akkor bukta.

Vagy mire gondoltál a "Nem egészen" kifejezés alatt?

Ha viszont nem túl sok adatról van szó, akkor query cachenél is simán gyorsabb lehet fájlban való cache-elés, mert jó esetben ezt memóriából fogja az OS kiszolgálni.

Egy folyamatosan használt gépen erre építeni eléggé hazárdírozás. Főleg ha minden egyes futáskor fel kell olvasni a PHP file-okat is.

Szerk.: Még annyit akartam hozzáfűzni, hogy file-ba akkor érdemes cache-elni ha sosem lesz clusterben az alkalmazásod (tehát mindíg csak egy gépen fog futni). Hálózaton filecache-t szinkronizálni (normális sebességgel) az már varázslat ;)
17

db vs file

Hodicska Gergely · 2008. Szep. 24. (Sze), 10.54
meggyőződésem hogy a MEMORY engine sokkal gyorsabb mint bármelyik diszk alapú engine.
Nem is írtam az ellenkezőjét. ;)

Vagy mire gondoltál a "Nem egészen" kifejezés alatt?
Arra, hogy nem a DB lesz feltétlenül a gyorsabb, fájl alapú cache simán gyorsabb lehet, kb. ugyanaz a szitu, mint a memcache esetén, egy sokkal egyszerűbb protokolon keresztül éred el az adatokat. Két link:
http://jpipes.com/index.php?/archives/100-Benchmarking-CacheEngine-vs.-the-MySQL-Query-Cache.html
http://www.mysqlperformanceblog.com/2006/08/09/cache-performance-comparison/

Még annyit akartam hozzáfűzni, hogy file-ba akkor érdemes cache-elni ha sosem lesz clusterben az alkalmazásod (tehát mindíg csak egy gépen fog futni).
Ez szintén eset függő, és független a file cache-től. Egyrészt jó lehet olyan szempontból is, hogy mindegyik szerveren más van, minden kérés másik gépre esik be, így egy rövid időre cache-elt random jellegű cucc még randomabb lesz, illetve az is lehet, hogy nem érdekel téged, hogy a különböző gépeken, adott kulcs alatt ha nem teljesen ugyanaz van, mert a látogatót nem fogja zavarni. Nálunk is van egy csomó ilyen cache.


Üdv,
Felhő