Přeskočit na obsah
Zapolu

4. června 2026, Luboš Zápotočný

Proč pokladna padá, když servery běží na 10 %

Servery mají rezervu, pokladna přesto selhává. Zámky v databázi, cache stampede a synchronní platební volání: poruchy, které autoscaling nevyřeší.

Je to jeden z nejmatoucnějších incidentů, jaké může e-commerce tým zažít. Kampaň odstartuje, pokladna začne narážet na časové limity a dashboardy přitom ukazují, že je všechno v pořádku: CPU na 10 %, paměť v klidu, dostatek rezerv. Instinkt velí přidat servery. Nové servery naběhnou, zůstanou nevytížené vedle stávajících a výpadek pokladny trvá dál.

Zmatek pramení ze špatného mentálního modelu. Zátěž má totiž dvě složky: práci a čekání. Vaše servery stojí ve frontě, a fronty na grafu CPU vidět nejsou.

Nejčastější příčiny

Soupeření o zámky v databázi. Pokladna je místo, kde e-shop přestává číst a začíná zapisovat: rezervovat sklad, založit objednávku, uložit adresu. Tyto zápisy se serializují na řádkových zámcích a provoz z kampaně je koncentruje do stejných několika nejčastěji zapisovaných řádků: sekvenčních čítačů objednávek, tabulek objednávek a košíků, rezervovaného skladu. Každá transakce drží své zámky, zatímco čeká na jinou práci. Propustnost se zhroutí, i když vytížení CPU zůstává nízké. Na Magentu se to v logu projeví jako chyby lock-wait timeout a deadlock z MySQL.

Cache stampede. Často žádaná položka v cache (stránka kategorie, na kterou míří každá reklama) vyprší uprostřed špičky. Každý požadavek, který ji v cache nenajde, teď generuje stránku znovu, všechny současně, a zatěžuje databázi identickými drahými dotazy. Databáze dostane jednu kopii té práce za každý souběžný požadavek.

Synchronní volání třetích stran přímo v pokladně. Ceny dopravy, autorizace platby, výpočet daně, anti-fraud kontrola. Každé z nich je síťové volání do cizího systému, provedené, zatímco váš worker drží spojení a často i databázovou transakci. Když jeden poskytovatel pod stejnou kampaňovou zátěží zpomalí z 200 ms na 10 sekund, každý worker postupně uvízne v tomto volání. Pokladna je pak nedostupná tak dlouho, dokud je ten poskytovatel pomalý.

Vyčerpání workerů a spojení. Tři výše uvedené problémy spojuje jeden zesilovač: workery, které čekají, pořád zabírají svůj slot i databázové spojení. PHP-FPM procesy nadimenzované na běžný provoz se zaplní zablokovanými požadavky, nové požadavky nedostanou worker ani spojení vůbec, a najednou selže všechno, co ještě potřebuje PHP worker, ať už na té stránce zbývá jakkoli málo práce.

Ani jeden z těch čtyř problémů není hardwarový problém, a právě proto autoscaling nepomůže: nové instance se zařadí do stejné fronty na stejný řádkový zámek za stejným pomalým dodavatelem. Přidaná kapacita čeká paralelně, místo aby zvýšila propustnost.

Jak to vidět předem

Diagnostický posun je od vytíženíčasu: kde tráví požadavek pokladny své milisekundy? Prací, nebo čekáním na zámky, cache a cizí API? Distribuované trasování na to odpovídá přímo; slow-query log a čítače čekání na zámcích v databázi na to odpovídají levně. Pokud před další kampaní přidáte jediný graf, ať jsou to čekání na zámcích.

Opravy plynou z diagnózy a většina z nich je rutinní: timeouty na každém volání třetí strany a cachované fallbacky tam, kde zastaralá odpověď neuškodí (mírně zastaralá cena dopravy nevadí, autorizace platby ale musí proběhnout v reálném čase), ochrana proti stampede, aby často žádaný klíč přestavoval jeden proces, zatímco ostatní vracejí starší verzi, přesun nepodstatných zápisů mimo transakci do fronty a rezervaci skladu tak pozdě ve funnelu, jak to byznys dovolí, a ne jeho blokování hned při vložení do košíku. Které z nich je podstatné pro váš e-shop, je empirická otázka. Audit výkonu na ni odpoví z vašich vlastních trasování a naše práce na DevOps udrží opravy funkční.

Většina těchto incidentů se ukáže být problémem souběžnosti, takže než začnete nakupovat servery, začněte u trasování.