Kontekst biznesowy i wyzwanie skali#
Wiodący europejski marketplace z segmentu Fashion & Retail stanął w obliczu krytycznego problemu skalowalności przed zbliżającym się sezonem wyprzedażowym Black Friday / Cyber Monday.
Dotychczasowa architektura monolityczna oparta o standardowy stack PHP-FPM oraz relacyjną bazę danych PostgreSQL zaczynała rzucać błędy HTTP 504 Gateway Timeout już przy 12 000 równoległych użytkowników (CCU).
Główne objawy niewydolności:#
- Blokady transakcyjne na bazie danych (Row-level locks): Synchroniczny koszyk i rezerwacja stanów magazynowych powodowały kaskadowe oczekiwanie transakcji.
- Dławienie PHP-FPM: Każde żądanie inicjalizowało od nowa cały framework aplikacji (bootstrap overhead ~45 ms per request), wysycając dostępną pulę workerów procesora.
- Utrata przychodów: Podczas poprzedniego Black Friday aż 4.8% transakcji zakończyło się błędem, generując bezpośrednie straty finansowe oraz degradację wizerunku marki.
Diagnoza architektoniczna i wąskie gardła (APM Profile)#
Prace diagnostyczne rozpoczęliśmy od 14-dniowego Sprintu Audytowego. Wykorzystując profilowanie APM oraz analizę pg_stat_statements, zidentyfikowaliśmy 3 krytyczne punkty zapalne:
- Synchroniczny łańcuch checkoutu: Jedno kliknięcie „Kupuję i płacę” wykonywało 14 synchronicznych zapytań SQL, weryfikację integracji płatności oraz odpytanie zewnętrznego systemu ERP.
- Brak strategii unikania Cache Stampede: Wygasanie kluczy najpopularniejszych produktów promocyjnych uderzało bezpośrednio w warstwę dyskową PostgreSQL (efekt Thundering Herd).
- Zarządzanie połączeniami: Brak odpowiedniego connection poolingu (PgBouncer) doprowadzał do przekraczania limitu 800 równoczesnych połączeń w bazie danych.
Zastosowane rozwiązanie inżynieryjne#
Zamiast ryzykownego przepisywania całego systemu od zera, wdrożyliśmy hybrydową architekturę transakcyjną z zachowaniem ciągłości operacyjnej sklepu:
1. Przejście na runtime RoadRunner (Worker Pools)#
Zastąpiliśmy klasyczny proces PHP-FPM długożyjącym serwerem aplikacyjnym RoadRunner napisanym w Go. Aplikacja utrzymuje zainicjalizowany stan w pamięci RAM, redukując czas bootstrapu z 45 ms do 1.2 ms.
2. Architektura Event-Driven (Asynchroniczny Checkout)#
Proces zatwierdzania zamówienia został rozdzielony na model zdarzeniowy oparty o RabbitMQ:
- Klient natychmiast otrzymuje potwierdzenie przyjęcia zgłoszenia do kolejki transakcyjnej (HTTP 202 Accepted w 18 ms).
- Pula dedykowanych workerów konsumuje zamówienia w kontrolowanym tempie dopasowanym do przepustowości bazy danych.
- Zaimplementowano Dead-Letter Exchanges (DLX) oraz pełną idempotencję operacji zapisu.
3. Redis Cluster ze Shardingiem Kluczy#
Wprowadziliśmy rozproszoną warstwę cache'u sesyjnego i stanów magazynowych z deterministycznym hashowaniem kluczy (Consistent Hashing) oraz mechanizmem Probabilistic Early Expiration (algorytm XFetch), całkowicie eliminującym zjawisko Cache Stampede.
[Klient / Web + Mobile]
│ (HTTPS / Traefik Reverse Proxy)
▼
[RoadRunner Go Workers Pool] ──(Session Cache)──► [Redis Cluster (6 Nodes)]
│
│ (Asynchroniczne zdarzenie: OrderPlaced)
▼
[RabbitMQ Cluster]
├── [Worker: Inventory Reserve]
├── [Worker: Payment Dispatch]
└── [Worker: PostgreSQL Transaction Pool (PgBouncer)]
Twarde rezultaty produkcyjne (Black Friday)#
Wdrożona architektura przeszła pomyślnie test bojowy podczas Black Friday, obsługując największy ruch transakcyjny w historii platformy:
- Przepustowość w peaku: Wzrost z 12 000 CCU (crash) do 65 000 równoległych użytkowników (+440%).
- Opóźnienie p99 transakcji: Redukcja z 1 450 ms do zaledwie 24.5 ms (-98.3%).
- Utracone zamówienia: Spadek z 4.8% błędów 504 do 0.000% (Zero order loss).
- Koszty infrastruktury chmurowej: Dzięki optymalizacji zużycia CPU i pamięci przez RoadRunner, koszt serwerów w przeliczeniu na 1000 obsłużonych zamówień spadł o 42%.
Wnioski i rekomendacje dla CTO / Zarządu#
- Skalowanie pionowe ma swoje granice: Dorzucanie mocniejszych maszyn w chmurze bez eliminacji blokad na bazie danych to tylko maskowanie długu technologicznego.
- Asynchroniczność to klucz do odporności: System nie musi przetwarzać wszystkiego synchronicznie w trakcie żądania HTTP użytkownika.
- Rygor pomiarów: Każda decyzja o refaktoringu musi wynikać z danych telemetrycznych (p95, p99, logi blokad locków), a nie intuicji.

