Caching af hierarkier leverer de hurtigste indlæsningstider, når jeg bruger hvert lag specifikt: opcode, page, browser og edge. Jeg viser i klare trin, hvordan jeg kombinerer disse lag, undgår konflikter og indstiller konfigurationer på en sådan måde, at anmodninger er kortere, og TTFB er synligt reduceret.
Centrale punkter
For at sikre, at overblikket er klart, opsummerer jeg først de centrale emner og tilpasser dem direkte til resultatmålene. Jeg forklarer alle niveauer med specifikke indstillinger, så implementeringen lykkes uden omveje. Jeg afgrænser klart de dynamiske dele for at bevare personaliseringen. Jeg optimerer headers og cachenøgler, så der ikke er unødigt spild i cachen. Endelig samler jeg alt i en stringent kæde, så hver hentning tager den hurtigste rute.
- Opkode accelererer PHP
- Side-cache forkortet TTFB
- Browser Sparer båndbredde
- Kant Reducerer ventetid
- Orkestrering Forhindrer konflikter
Hvad betyder „caching-hierarkier“ egentlig?
Jeg forstår ved Hierarki forskudt caching fra serverkernen til slutenheden. Hvert lag besvarer et andet spørgsmål: Skal serveren rekompilere kode, skal PHP gengive siden, skal browseren genindlæse aktiver, eller skal en edge node levere færdigt indhold tæt på brugeren. Jeg undgår dobbeltarbejde ved at harmonisere niveauerne og tildele klare ansvarsområder. På den måde reducerer jeg CPU-belastningen, backend-forespørgsler og netværkslatens uden at miste funktionalitet. Jeg kan finde en kort introduktion til niveauerne i denne kompakte guide: Enkle caching-niveauer.
Opcode-caching: Gør PHP hurtigere med det samme
På Opkode-caching opbevarer jeg kompileret PHP-bytekode i RAM og sparer mig selv for gentagen parsing. Det fremskynder alle anmodninger, der berører PHP, især CMS-arbejdsbelastninger som WordPress. Jeg aktiverer OPcache og dimensionerer hukommelsen generøst nok til, at hyppige scripts aldrig bliver fortrængt. Jeg indstiller moderat revalidering, så ændringer forbliver synlige med det samme uden at tjekke for ofte. På den måde reducerer jeg både CPU-belastningen og svartiderne mærkbart.
Jeg indstiller bevidst typiske OPcache-parametre i php.ini konservativt, overvåger hitraten og justerer efter behov. Jeg holder antallet af accelererede filer højt nok til, at projektet passer helt ind. Jeg bruger preloading til centrale klasser, så selv koldstarter kører hurtigere. Jeg implementerer ændringer med en nulstilling af cachen for at undgå at risikere inkonsistente tilstande. Jeg bruger konfigurationsblokken som et udgangspunkt og ikke som et stift dogme.
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=2
Jeg tjekker regelmæssigt OPcache-statistikker, fordi kun målinger viser, om cachen bærer eller ikke bærer. Hosting-dashboards eller PHP-statussider hjælper mig med at minimere antallet af misses. Jeg undgår hukommelsesværdier, der er for små og fører til evictions. Jeg undgår også sjældne valideringer, så produktive ændringer ikke sidder fast. Med denne balance arbejder jeg effektivt og sikkert.
Caching af sider: HTML uden ventetid
På Side-cache Jeg gemmer den færdige HTML, så PHP og databasen slet ikke kører længere. Dette reducerer TTFB drastisk og giver de største spring under belastning. Jeg udelukker konsekvent personaliserede stier som indkøbskurven, kassen og brugerkonti. Samtidig indkapsler jeg små dynamiske dele via AJAX eller edge-side includes, så resten kan komme hårdt fra cachen. Det holder siden hurtig uden at miste vigtig individualitet.
Jeg beslutter, om jeg vil bruge caching på serverniveau eller arbejde med et plugin. På serveren opnår jeg det bedste Forsinkelse, Plugins giver mig fleksibel kontrol over CMS'et. Preload-mekanismer fylder cachen på forhånd, så de første kald ikke skal vente. Jeg rydder op i forældreløse poster ved hjælp af rensningsregler, når jeg opdaterer indhold. For særligt dyre områder kombinerer jeg også objektcache, så databaseadgange er mindre hyppige.
Browser-caching: Hold aktiverne lokale
På Browser-Jeg efterlader statiske filer som billeder, CSS og JS i den lokale cache. Tilbagevendende besøgende indlæser så næsten ingenting, og serveren forbliver fri. Jeg indstiller lange max-age-værdier for uforanderlige aktiver, som jeg forsyner med versionering af filnavne. Jeg tilføjer korte tider eller must-revalidate til dynamiske endpoints, så appen forbliver opdateret. På den måde reducerer jeg båndbredden og optimerer den opfattede hastighed.
Jeg er opmærksom på en ren blanding af cache control, ETag og last-modified. For uforanderlige filer indstiller jeg immutable, så browseren ikke tjekker unødigt. Til ressourcer med hyppige opdateringer bruger jeg betingede anmodninger via ETag. Jeg undgår tvetydige headere, fordi modstridende signaler fører til misforståelser. Jeg holder kontrollen direkte på webserveren eller via CMS-plugin, afhængigt af mit miljø.
Edge-caching: nærhed til brugeren
Omkring Kant-netværk leverer jeg indhold i globale PoP'er, hvilket minimerer ventetiden og udjævner spidsbelastninger. HTML, billeder og API'er kan serveres tæt på brugeren afhængigt af regelsættet. Jeg arbejder med cachenøgler, der kun indeholder nødvendige variabler for at minimere fragmentering. Regler som stale-while-revalidate og stale-if-error sikrer, at brugerne straks ser en gyldig kopi, selv om Origin kun lige er ved at varme op. Internationale målgrupper nyder især godt af det, fordi routing-tiderne reduceres mærkbart.
Jeg adskiller varianter, når mobil og desktop er meget forskellige. Jeg udelader bevidst checkout- og kontoområdet i udkanten for at undgå kollisioner med sessioner og cookies. Jeg tjekker regelmæssigt hitraten og justerer TTL'er, indtil optimale odds er opnået. Et praktisk og dybdegående kig på dette Guide til edge-caching med fokus på latenstid og netværksstier. Jeg har rene udrensningsstrategier ved hånden, så opdateringer træder i kraft med det samme i hele verden.
Indstil HTTP-header korrekt
Die Overskrift styre, hvor langt indholdet må rejse, og hvornår det skal revalideres. Jeg bruger cache-kontrol til at bestemme synlighed, levetid og revalideringsforpligtelser. ETag identificerer entydigt en ressource og muliggør if-none-match-anmodninger. Last-Modified giver et fallback for klienter, der ignorerer ETags. Jeg holder kombinationen klar, så klient, CDN og oprindelse har de samme forventninger.
Jeg bruger følgende oversigt som en praktisk reference under konfigurationen. Jeg tjekker hver linje i forhold til ressourcetypen og ændringsadfærden. For statiske filer indstiller jeg lange max-age-værdier med immutable. For hyppigt opdateret indhold reducerer jeg varigheden og benytter mig af betingede anmodninger. Det holder datastien effektiv og korrekt.
| Overskrift | Funktion |
|---|---|
| Cache-kontrol | Kontrollerer varighed, synlighed, revalidering (f.eks. max-age, public, must-revalidate) |
| ETag | Unik identifikation af en version, grundlag for betingede kald |
| Sidst ændret | Tidsstempel som alternativ til ETag, bruges til validering |
Strategier for ugyldiggørelse og friskhed i cachen
Jeg planlægger Invalidering lige så omhyggeligt som selve cachelagringen. Selektiv udrensning efter ID, tag eller sti forhindrer fuld udrensning, som medfører omkostninger. Når jeg implementerer, renser jeg kun det, der virkelig har ændret sig. Stale-while-revalidate holder brugerne hurtige, mens baggrunden indlæser friske kopier. Stale-if-error fanger fejl på Origin uden at forringe brugeroplevelsen.
Jeg kombinerer kort TTL med en høj hitrate, hvis indholdet roterer ofte. Til arkiver, medier og biblioteker vælger jeg lange tider, versionerer filnavne og fjerner check loads. Dashboards på CDN- eller serversiden viser mig, hvor cache-buckets er for små. Så justerer jeg antallet af slots og objektstørrelser. Denne konstante finjustering gør hele forskellen i hverdagen.
Cache-nøgler, cookies og Vary
Med slank Nøgler Jeg holder antallet af varianter lavt. Kun parametre, der virkelig ændrer resultatet, ender i nøglen. Jeg bruger bevidst Vary-overskrifter, f.eks. efter Accept-Encoding- eller User-Agent-klasser, hvis det er nødvendigt. For mange cookies i nøglen bryder cachen op og reducerer hitraten. Jeg rydder op i ubrugte cookies og regulerer parametre, der bruges til sporing, ud af nøglen.
Hvis jeg har brug for at variere sprog, valutaer eller layout, bruger jeg specifikke nøgler som lang=de eller currency=EUR. Jeg begrænser denne variation til de tilfælde, jeg virkelig har brug for. Til A/B-tests adskiller jeg kun de segmenter, der har forskelligt indhold. Jeg håndterer alt andet på klientsiden eller via edge-logik uden nøgleeksplosion. Det er sådan, jeg holder den globale cache effektiv.
Objektcache og transienter
En Objekt-Cache reducerer dyre databaseforespørgsler ved at holde resultaterne i hukommelsen. Til WordPress vælger jeg Redis eller Memcached for at sikre hurtig adgang til ofte ønskede indstillinger, forespørgsler og sessioner. Jeg bruger transienter til midlertidigt at gemme dyre beregninger. Jeg rydder op i disse værdier under implementeringen, når afhængighederne ændres. Det holder siden dynamisk og stadig hurtig.
Denne sammenligning hjælper mig med projektstørrelser med intensiv datalast: Redis vs Memcached. Der genkender jeg de typiske styrker ved begge systemer afhængigt af arbejdsbyrden. Jeg dimensionerer RAM og tjekker eviction-strategier for at gøre plads til sjældent brugte objekter. Overvågning af hit/miss-rater viser, om konfigurationen fungerer. Dette niveau supplerer ideelt set sidecachen.
Kombination: Den optimerede kæde
Jeg kombinerer Niveauer så hver anmodning tager den korteste vej. OPcache fremskynder genereringen, når HTML rent faktisk oprettes. Sidecachen giver færdiglavet markup til anonyme besøgende. Browsercaching forhindrer gentagne overførsler af aktiver, og Edge distribuerer indholdet globalt. Til allersidst er der en ren udrensnings- og versioneringsstrategi, så opdateringer træder i kraft med det samme.
Jeg har følgende tabel ved hånden som et snydeark, når jeg justerer indstillingerne. Jeg læser kolonnen „Konfiguration“ som en to-do-liste under implementeringen. Jeg sørger for, at niveauerne supplerer hinanden og ikke ophæver hinanden. Det holder den overordnede arkitektur klar og effektiv. Dette overblik forhindrer fejl under planlægningen.
| Cache-niveau | Fordel | Typisk indhold | Konfiguration |
|---|---|---|---|
| Opkode | Hurtig udførelse af PHP | PHP-bytekode | php.ini, Server-panel |
| Side | Lav TTFB | Færdig HTML | Serverniveau eller plugin |
| Browser | Lokal genanvendelse | CSS, JS, billeder | HTTP-overskrift, versionering |
| Kant | Global nærhed | HTML og aktiver | CDN-regler, nøgler, udrensning |
Måling: TTFB, LCP og hitrater
Jeg måler TTFB, for at se, hvor hurtigt den første byte ankommer. LCP viser mig, om det synlige indhold vises til tiden. Jeg bruger cache-analyser til at tjekke hitrater og genkende ruter, hvor misses ophobes. Jeg sammenholder målinger med implementeringer, crawlerbelastning og trafiktoppe. Kun tal viser, hvor jeg skal stramme skruerne.
Jeg logger svarhoveder som alder og CF-cachestatus for at visualisere succeser på kanten. Serverlogs fortæller mig, om sidecachen fungerer korrekt. Hvis der er store afvigelser, leder jeg efter cookies, forespørgselsparametre eller variabler, der opdeler cachen. Jeg tester varianter med og uden en indlogget tilstand. På den måde kan jeg hurtigt finde de justeringer, der giver en stabil hastighed.
Typiske fejl og rettelser
For mange Varianter i cachen er en hyppig bremseklods. Jeg reducerer forespørgselsparametre i nøglen og neutraliserer sporingsparametre. En anden klassiker er modstridende headere, f.eks. no-store sammen med en lang max-age. Tomme eller forkerte purges kan også give indtryk af, at cachen ikke fungerer. Jeg løser hurtigt sådanne problemer med klare regler og logs.
Et andet problem er plugins, der skriver dynamisk indhold, som er hard-coded i HTML. Jeg flytter sådanne elementer til fragmenterede endpoints, der caches eller genindlæses uafhængigt. Cookies blokerer ofte edge-cachen utilsigtet; jeg sletter unødvendige cookies på et tidligt tidspunkt. Dårlig versionering tvinger browsere til at genindlæse igen og igen; jeg nummererer filer konsekvent. Det holder pipelinen ren og modstandsdygtig.
Beslutningstræ: Hvem svarer på en henvendelse?
Jeg definerer en klar beslutningsvej for at afgøre, hvilket niveau der må leveres. På den måde undgår man unødvendige origin-hits og reducerer TTFB på en reproducerbar måde.
- 1) Er ressourcen uforanderlig (versioneret fil)? Browsercache med lang max-age og uforanderlig.
- 2) Er anmodningen anonym, GET og uden følsomme cookies? Edge/side-cache med public, s-maxage og stale-while-revalidate.
- 3) Indeholder anmodningen Auth-Cookies, Authorisation-Header eller er den POST? Origin, eventuelt med Object-Cache.
- 4) Indeholder URL'en kun kosmetiske parametre (utm, fbclid)? Jeg fjerner dem fra cachenøglen.
- 5) Har du brug for små live-dele (f.eks. antal indkøbskurve)? Fragmenteret via AJAX eller ESI.
// pseudo-logik
if (immutable_asset) return browser_cache;
if (is_get && is_anonymous && cacheable) return edge_or_page_cache;
if (needs_fragment) return cached_html + dynamic_fragment;
return origin_with_object_cache; Mestring af fragmentering: ESI, AJAX og delvis gengivelse
Jeg isolerer dynamiske øer, så resten kan cache hårdt. ESI er velegnet til injektioner på serversiden (f.eks. personaliserede blokke), AJAX til genindlæsningspunkter på klientsiden. Det er vigtigt, at fragmenter får deres egen, korte TTL, så de forbliver opdaterede uden at ugyldiggøre hele dokumentet.
- Statisk basisramme: lang TTL, offentlig, s-maxage, stale-while-revalidate.
- Dynamisk fragment: kort TTL, must-revalidate eller no-store, hvis det er personaliseret.
- Fejltilfælde: stale-if-error på HTML-indpakningen forhindrer hvide sider.
// Eksempel på header til HTML-konvolut
Cache-Control: public, max-age=0, s-maxage=600, stale-while-revalidate=60, stale-if-error=86400
// Eksempel på header til personligt fragment
Cache-kontrol: privat, no-store Undgå cache-stormløb og styr opvarmningen
Jeg forhindrer flokvirkninger, hvor mange samtidige fejl oversvømmer Origin. Blød TTL/hård TTL, sammenlægning af anmodninger og låsning er mine værktøjer. Jeg bruger preloadere, der cyklisk varmer sitemaps eller vigtige stier op og forskyder TTL'er, så ikke alt udløber på samme tid.
- Blød TTL: En worker kan forny udløbne objekter, mens andre forbrugere stadig modtager forældede.
- Sammenlægning: Samtidige anmodninger om den samme nøgle slås sammen.
- Forskudte TTL'er: Kritiske sider får forskudte runtimes for at udjævne rensningsbølger.
// Eksempel på graduerede runtimes
/home, /category/* -> s-maxage=900
/article/* -> s-maxage=1800
/search -> s-maxage=120, stale-while-revalidate=30 Juster TTL-designet rent i kæden
Jeg indstiller browser-, edge- og origin-TTL'er, så revalidering sker, hvor det er mest fordelagtigt. For HTML stoler jeg på s-maxage på kanten og holder max-age lav i browseren for at garantere hurtige udrensninger. For aktiver vender jeg det om: meget lange browser TTL'er, fordi versionering sikrer aktualitet.
// HTML
Cache-Control: public, max-age=0, s-maxage=600, stale-while-revalidate=60
// Versionerede aktiver
Cache-kontrol: offentlig, max-age=31536000, uforanderlig Jeg undgår modstridende specifikationer som no-cache sammen med immutable. Klare regler skaber ensartede resultater i hele hierarkiet.
Komprimering, HTTP/2/3 og prioritering
Jeg aktiverer Gzip/Brotli og indstiller Vary-headeren korrekt, så varianter adskilles rent. Med HTTP/2/3 drager jeg fordel af multiplexing og prioritering; dette reducerer head-of-line-blokering, når mange aktiver indlæses parallelt.
# NGINX-eksempel
gzip på;
gzip_types text/css application/javascript application/json image/svg+xml;
brotli on;
brotli_types text/css application/javascript application/json image/svg+xml;
add_header Vary "Accept-Encoding" altid;
# Lang browser TTL for aktiver
placering ~* .(css|js|svg|woff2|jpg|png)$ {
udløber 1 år;
add_header Cache-Control "public, max-age=31536000, immutable";
} Autentificering, cookies og sikkerhed
Jeg cacher aldrig personligt indhold offentligt. Jeg markerer anmodninger med autorisationsheaders eller sessionscookies som private eller omgår specifikt edge-cachen. Samtidig hvidlister jeg kun vigtige cookies, så cachenøglen forbliver slank.
- Login-/kontoområder: Cache-kontrol: privat eller no-store.
- Offentlige HTML-sider: offentlig, s-maxage; undgå at sætte cookie.
- Cookie-hygiejne: Fjern irrelevante cookies (f.eks. sporing) fra nøglen.
// VCL-lignende logik
if (req.http.Authorisation) { return(pass); }
if (req.http.Cookie ~ "session=") { return(pass); }
// Kun nødvendige cookies i nøglen
unset req.http.Cookie: ".*";
Cache API og søgeendpunkter effektivt
Jeg skelner skarpt mellem metoderne: GET kan cachelagres, POST normalt ikke. Ved hyppige søgninger indstiller jeg korte s-maxage-værdier plus stale-while-revalidate for at udjævne svartiderne. Jeg cacher kun svar med 4xx/5xx-fejl kortvarigt eller slet ikke, så rettelser træder i kraft med det samme.
// Eksempel på header til offentlig GET API
Cache-Control: public, max-age=0, s-maxage=120, stale-while-revalidate=30
// Cache fejl sparsomt
Cache-kontrol: offentlig, s-maxage=10 Observerbarhed: overskrifter, logfiler og TTFB-kontrol
Jeg bruger header-inspektion og logfiler til at gøre kæden gennemsigtig. Alder, hit/miss-indikatorer og upstream-status viser mig, hvor der går tid tabt. Jeg bruger enkle værktøjer til at tjekke TTFB på en reproducerbar måde og finde outliers.
Mål # TTFB
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}sn" https://example.org
Tjek #-overskriften
curl -I https://example.org | sed -n '1,20p' # NGINX-log med cache-status
log_format timed '$remote_addr "$request" $status $body_bytes_sent '
'$upstream_cache_status $upstream_response_time $request_time';
access_log /var/log/nginx/access.log timed; Jeg sammenligner logdata med udrulninger og rensninger. Høje miss-toppe direkte efter udrulninger indikerer en manglende opvarmning eller TTL'er, der er for korte. Hvis Age forbliver permanent lav, tjekker jeg, om cookies utilsigtet omgår edge-cachen.
Implementering: versionering og rullende oprydning
Jeg bygger versioner ind i filnavne (f.eks. app.9f3c1.js), så browserens caching kan være aggressiv. Til HTML bruger jeg rullende udrensninger, der opdaterer kritiske sider først, efterfulgt af dybde og long-runners. Blå/grønne implementeringer afkobler build fra release og giver mig tid til specifikt at varme cacher op.
// Asset-pipeline
style.[hash].css
app.[hash].js
// HTML henviser altid til nye hashes Jeg planlægger rensningsvinduer uden for spidsbelastningstidspunkterne og overvåger hitraten umiddelbart efter. På den måde undgår jeg spidsbelastninger på Origin.
Billedvarianter, DPR og responsiv caching
Jeg genererer billedvarianter (størrelse, format) på en deterministisk måde, så cachenøglen forbliver stabil. For WebP/AVIF-varianter adskiller jeg eksplicit via filsti eller parametre i stedet for bare via Accept-overskrifter for at undgå Vary-eksplosioner. Til skærme med høj opløsning (DPR) bruger jeg srcset/sizes, som giver browseren mulighed for at vælge den bedste variant, og cachen træder i kraft for hvert enkelt aktiv.
<img src="img/hero-1024.jpg"
srcset="img/hero-768.jpg 768w, img/hero-1024.jpg 1024w, img/hero-1600.jpg 1600w"
sizes="(max-width: 768px) 90vw, 1024px" alt=""> Jeg holder antallet af varianter pr. motiv lavt og fjerner forældede størrelser fra pipelinen, så cachen ikke fragmenteres.
Kapacitetsplanlægning: cache-hukommelse og objektstørrelser
Jeg dimensionerer cachen efter reelle adgangsmønstre: Nogle få store objekter (billeder, videoer) kræver andre strategier end mange små (HTML, JSON). Jeg sætter grænser for den maksimale objektstørrelse og kontrollerer, om populære objekter forbliver i hukommelsen. En høj genbrugsrate er vigtigere end absolut størrelse; jeg trimmer derfor nøgler, fletter varianter og forhindrer duplikater.
// Eksempel: Grænser
max_object_size = 10m
standard_ttl = 600
nuke_limit = moderat (udsættelser uden stalls) Praktisk tjekliste til implementering
Jeg aktiverer OPcache med tilstrækkelig hukommelse og tjekker hitraten. Derefter sætter jeg sidecaching op, udelukker kritiske stier og forudindlæser vigtige URL'er. Derefter indstiller jeg browserheaders med lange tider for uforanderlige filer og versionering. I CDN'et definerer jeg cachenøgler, TTL'er og rensningsstrategier og aktiverer stale-while-revalidate. Til sidst bruger jeg måleværktøjer til at kontrollere, om TTFB, LCP og edge hit rate når målene.
Kort resumé
Jeg bruger Caching hierarkisk: OPcache accelererer koden, sidecachen leverer HTML, browserheaders holder aktiverne lokale, og Edge bringer indholdet tæt på brugerne. Med klare nøgler, passende TTL'er og smart ugyldiggørelse reducerer jeg serverbelastning, båndbredde og ventetid. Målte værdier sikrer fremskridt og viser optimeringspotentialet. Dette skaber en pålidelig kæde fra oprindelsen til slutenheden. Alle, der leder efter yderligere detaljer om global levering, vil finde nok udgangspunkter i praksis til at gøre deres egen arkitektur mærkbart hurtigere.


