Cache-elés folyamata
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?
■ 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?
Az érvényesség ellenőrzését ...
szituációtól függ
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ő
Egyke minta (a.k.a. singleton pattern)
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!
Depending caches
Hol tároldójon a cache
Váratlan válasz
Nade viccet félre. Szerintem attól függ. Megfelelő adatbáziskonfig mellett (pl. mysql memóriatáble) sokkal gyorsabb lesz adatbázissal.
Egy infót kifelejtettem ...
Hát innen számítva járhatsz
Ajánlom hogy valahogy inkább memóriába zsúfold bele valahogy (shmem?)
fájl cache lehet jobb a mysqlnél
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ő
Van opcode cache ...
Az alatt pontosan mit értünk, hogy nekem kell eltakarítani a cache-t?
szezon vs fazon ;)
Üdv,
Felhő
APC van
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)?
Szolgáltatló?
Re: szolgáltató
APC cache_by_default
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?
két apró
é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.
Auth
Kontra
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?
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 ;)
db vs file
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/
Üdv,
Felhő