Page cache on yksi tehokkaimmista tavoista nopeuttaa WordPress-sivustoa. Oikein toteutettuna se voi vähentää PHP:n ja tietokannan kuormaa yli 90 prosenttia. Välimuistiin liittyy kuitenkin yksi vakava ongelma, joka näkyy erityisesti korkean liikenteen sivustoilla: cache stampede.
Cache stampede syntyy, kun suuri määrä käyttäjiä yrittää samanaikaisesti rakentaa uudelleen vanhentunutta välimuistia. Sen seurauksena palvelin voi kuormittua hetkessä moninkertaisesti enemmän kuin ilman välimuistia.
Monissa tapauksissa juuri cache stampede aiheuttaa suorituskykyongelmia, vaikka välimuisti olisi muuten oikein konfiguroitu.
Mikä on cache stampede?
Tilanne alkaa yleensä näin:
Cached Page
↓
TTL expires
↓
Cache deleted
Seuraava käyttäjä joutuu rakentamaan sivun uudelleen.
Ongelma syntyy, kun samaan aikaan saapuu paljon käyttäjiä.
100 visitors
↓
Cache expired
↓
100 cache rebuilds
Sen sijaan että yksi käyttäjä rakentaisi välimuistin, kaikki tekevät saman työn yhtä aikaa.
Miksi ilmiö on vaarallinen?
Yksi raskas sivu voi sisältää:
- kymmeniä tietokantakyselyitä
- ulkoisia API-kutsuja
- WooCommerce-laskentaa
- dynaamista sisältöä
Normaalisti:
1 render
↓
cache
↓
100 visitors
Stampedessa:
100 visitors
↓
100 renders
Kuorma kasvaa eksponentiaalisesti.
Tyypillinen WordPress-esimerkki
Etusivu:
TTL = 1 hour
Kun tunti täyttyy:
Cache purge
↓
Traffic spike
↓
CPU 100%
Sivusto voi hidastua merkittävästi tai jopa kaatua.
Page cache ei ole ainoa ongelma
Stampede voi tapahtua myös:
- transienteissa
- Redis-välimuistissa
- REST API -vastauksissa
- query-cacheissa
- object cache -kerroksissa
Kyseessä on yleinen välimuistiarkkitehtuurin ongelma.
Locking on tärkein ratkaisu
Yleisin tapa estää stampede on lukitus.
Prosessi:
Cache Miss
↓
Acquire Lock
↓
Generate Cache
↓
Release Lock
Muut käyttäjät odottavat valmiin välimuistin syntymistä.
Redis Locking
Redis soveltuu tähän hyvin.
Esimerkki:
$lock = wp_cache_add(
'homepage_lock',
true,
'locks',
30
);
Vain yksi prosessi saa lukon.
Muut odottavat.
Transient Lock
Yksinkertainen vaihtoehto:
if (!get_transient('cache_lock')) {
set_transient(
'cache_lock',
true,
30
);
}
Ei yhtä luotettava kuin Redis, mutta toimii pienissä ympäristöissä.
Stale Cache
Moderni ratkaisu on tarjota vanhentunut cache käyttäjälle.
Malli:
Cache expired
↓
Serve stale content
↓
Refresh in background
Käyttäjä saa nopean vastauksen.
Palvelin rakentaa uuden välimuistin taustalla.
Stale-While-Revalidate
Tätä mallia käyttävät esimerkiksi:
- Cloudflare
- Fastly
- Varnish
Prosessi:
User Request
↓
Expired Cache
↓
Serve Stale Version
↓
Background Regeneration
Käyttäjä ei huomaa mitään.
Soft TTL ja Hard TTL
Yksi tehokas tekniikka.
Esimerkki:
Soft TTL = 1h
Hard TTL = 2h
Soft TTL:n jälkeen:
- cache voidaan päivittää
Hard TTL:n jälkeen:
- cache poistetaan pakolla
Näin vältetään yhtäkkiset rebuild-piikit.
Cache Warming
Toinen tehokas ratkaisu.
Sen sijaan että käyttäjä rakentaa välimuistin:
Content Update
↓
Cache Purge
↓
Warmup Job
↓
Cache Ready
Käyttäjät saavat aina lämpimän välimuistin.
Queue-pohjainen regenerointi
Suurissa ympäristöissä:
Cache Miss
↓
Queue Job
↓
Worker
↓
Cache Rebuild
Tämä estää useita samanaikaisia rakennuksia.
WooCommerce ja stampede
WooCommerce on erityisen altis ongelmalle.
Esimerkiksi:
- kategoriat
- tuotesivut
- kampanjasivut
voivat saada suuren liikennepiikin heti cache purge -tapahtuman jälkeen.
Edge Cache vähentää riskiä
Arkkitehtuuri:
Visitor
↓
CDN Edge Cache
↓
Origin
Useimmat käyttäjät eivät koskaan osu origin-palvelimeen.
Cache Invalidation
Liian aggressiivinen invalidointi aiheuttaa ongelmia.
Huono:
Save Post
↓
Purge Entire Site
Parempi:
Save Post
↓
Purge Related Pages
Tällöin vain pieni osa välimuistista rakennetaan uudelleen.
Monitorointi
Seuraa:
- cache hit ratio
- regeneration time
- Redis hits
- CPU usage
- TTFB
Erityisesti:
Cache Miss Rate
paljastaa stampede-ongelmat nopeasti.
Cloudflare ja stampede
Cloudflare tarjoaa:
- Cache Reserve
- Tiered Cache
- Cache Locking
- Stale While Revalidate
Nämä vähentävät origin-kuormaa merkittävästi.
Yleisimmät virheet
- ei lockingia
- koko sivuston purge jokaisessa päivityksessä
- ei cache warmingia
- liian lyhyt TTL
- ei stale-cache-strategiaa
- WooCommerce-sivujen väärä cache-konfiguraatio
Paras käytännön arkkitehtuuri
CDN
↓
Edge Cache
↓
Redis Locking
↓
WordPress
↓
Database
Lisäksi:
Stale While Revalidate
+
Cache Warming
+
Selective Purge
Yhteenveto
Cache stampede on tilanne, jossa suuri määrä käyttäjiä yrittää samanaikaisesti rakentaa vanhentunutta välimuistia. Se voi aiheuttaa massiivisen kuormituspiikin juuri silloin, kun välimuistin pitäisi parantaa suorituskykyä.
Paras suoja muodostuu yhdistämällä locking, stale-while-revalidate, cache warming ja tarkasti kohdistettu cache invalidointi. Näin WordPress pystyy käsittelemään suuria liikennemääriä ilman että välimuistin vanheneminen aiheuttaa suorituskykyongelmia.