Bir məhsul buraxılışı elan olunur, geri sayım bitir və minlərlə alıcı eyni saniyələrdə səhifəni yeniləyir. Bir qismi məhsula baxır, digərləri səbətə əlavə edir, ən bahalı qrup isə checkout və ödəniş axınına keçir. Flash sale zamanı sistemin dərdi trafik sayından çox onun formasıdır: yük qəfil gəlir və platformanın kiçik bir hissəsinə yığılır.
Shopify kimi çox mağazalı platformada vəziyyət daha incədir. Bir məşhur mağazanın kampaniyası həmin mağazanı yavaşlada bilər, amma başqa satıcıların biznesini özü ilə aparmamalıdır. Sistem dizaynının əsas sualı buna görə “neçə request qəbul edə bilərik?” deyil. Daha faydalı sual budur: “bir mağazanın qeyri-adi yükünü necə məhdudlaşdırıb alış axınını işlək saxlaya bilərik?”
Flash sale niyə sistemi fərqli sıxır?
Normal gündə baxış, axtarış və alış request-ləri vaxta və mağazalara yayılır. Flash sale isə yüzlərlə fərqli URL-ə bərabər paylanmış trafik yaratmır. Hamı eyni məhsulu istəyir. Keşlənən şəkil və CSS faylı ucuz başa gəlsə də, stok yoxlaması, səbətin dəyişdirilməsi, endirim hesablanması və sifarişin yazılması shared state üzərində işləyir.
Bu fərq capacity planlamada tez gözdən qaçır. Shopify-ın performans testləri haqqında texniki yazısında vurğulandığı kimi, bütün request-lər eyni xərcə malik deyil. Saniyədə yüz min statik fayl cavabı sistemin checkout-da saniyədə daha az sayda write əməliyyatına dözəcəyini sübut etmir. CPU boş görünə bilər, amma database connection pool, lock gözləməsi və ya üçüncü tərəf payment inteqrasiyası artıq boğulur.
Üstəlik, son məhsulu almağa çalışan istifadəçi uğursuz cavabdan sonra sakitcə getmir. Səhifəni yeniləyir, düyməni yenidən basır, mobil tətbiqi açır. Retry nəzarətsizdirsə, ilkin pikdən yaranan problem öz yükünü artıran dövrəyə çevrilir. Ona görə backpressure, timeout və idempotency checkout-un kənar bəzəyi deyil, pik anının əsas müdafiəsidir.
Məsələ burada qəlizləşir.
Sistem bütün request-ləri növbəyə qəbul edib gec də olsa cavablandırmağa çalışsa, queue böyüdükcə istifadəçinin gözləmə müddəti də artır. Client timeout verdikdən sonra görülən iş hətta faydasız ola bilər. Məhdud queue, erkən overload cavabı və exponential backoff sistemi bərpa oluna bilən vəziyyətdə saxlayır; gözləmə otağı isə alıcı axınını checkout-un real tutumuna uyğun tempə sala bilər. Bu tədbirlər satışın biznes qaydaları ilə razılaşdırılmalıdır, çünki texniki baxımdan sağlam throttle ədalətsiz məhsul bölgüsü yarada bilər.
Pod arxitekturası yükü platformadan ayırır
Shopify əvvəl database-i shard-lara bölərək üfüqi miqyaslama qazandı. Təkcə sharding yetərli deyildi: hər hansı shard-a bağlı əməliyyat bütün shard-ları gəzməli olsaydı, bir nasazlıq platforma səviyyəli problemə çevrilə bilərdi. Bunun qarşısını almaq üçün runtime pod-lara bölündü. Buradakı pod Kubernetes pod-u deyil; müəyyən mağazaları ayrıca datastore dəstində saxlayan izolyasiya vahididir.
Shopify-ın pod arxitekturasında hər web request və delayed job bir pod-a aid edilir. Load balancer qarşısındakı routing məntiqi mağazanı tapır, request-ə uyğun pod məlumatını əlavə edir və onu həmin istiqamətə göndərir. Application server də yalnız seçilmiş pod-un datastore-ları ilə işləyir.
Diaqram — orijinal məqalədə
Diaqramdakı sərhəd vacibdir. Məşhur mağaza Pod 1-də ağır yük yaradırsa, onun database vaxtını Pod 2-dəki mağazalarla birbaşa bölüşmür. App server və load balancer kimi bəzi resurslar ortaq qala bilər, lakin bir iş vahidi eyni anda pod-lar arasında gəzişmir. Bu, həm failure blast radius-u kiçildir, həm də yeni pod əlavə etməklə capacity-ni böyütməyə imkan verir.
İzolyasiya pulsuz gəlmir. Routing cədvəli düzgün və sürətli olmalı, background job da web request kimi mağaza kontekstini daşımalı, cross-pod əməliyyatlar isə dizayn səviyyəsində məhdudlaşdırılmalıdır. Əks halda shard var, amma nasazlıq sərhədi kağız üzərində qalır.
Oxuma yolunu ucuzlaşdırmaq, yazma yolunu qorumaq
Flash sale trafikinin böyük hissəsi əvvəlcə storefront-a dəyir. Statik asset-lərin CDN-dən verilməsi və təhlükəsiz oxuma cavablarının cache-də saxlanması origin yükünü azaldır. Lakin stok və qiymət kimi tez dəyişən məlumatı uzun müddət cache-də saxlamaq başqa problem yaradır: sürətli, amma köhnə cavab.
Burada məqsəd hər şeyi cache etmək deyil. Məhsul şəkli ilə “son ədəd qalıb” məlumatının freshness tələbi eyni ola bilməz. Oxuma yolunda qısa TTL, düzgün invalidation və sorğuların birləşdirilməsi origin-i qoruyur; sifariş yaradılan yazma yolunda isə correctness üstün tutulur. Eyni son vahidi iki alıcıya satmamaq üçün stok dəyişikliyi atomik qərar tələb edir.
Checkout da mümkün qədər dar saxlanmalıdır. Analytics, e-poçt və digər yan təsirlər sifarişin qəbul edilməsi üçün məcburi deyilsə, onları sinxron kritik yola yığmaq latency-ni və nasazlıq ehtimalını artırır. Queue bu işləri ayıra bilər, amma sifarişin özündə idempotency açarı lazımdır. İstifadəçi və ya gateway eyni əməliyyatı təkrarlayanda sistem ikinci sifariş yaratmamalıdır.
Queue isə sonsuz anbar deyil. Consumer-lər producer-lərdən uzun müddət geri qalırsa, “sifarişi qəbul etdik” cavabının arxasında saatlarla gecikən əməliyyatlar qala bilər. Queue depth, ən köhnə mesajın yaşı və consumer throughput birlikdə izlənməlidir. Kritik sifariş hadisələri ilə aşağı prioritetli analytics mesajlarını eyni növbədə saxlamaq da təhlükəlidir; ikinci qrupun sıçrayışı birinci qrupun gecikməsini artırmamalıdır.
Pik gün məşq edilmədən idarə olunmur
Capacity rəqəmi production-a yaxın workload olmadan az şey deyir. Bəzən heç nə demir. Load test məlum request səviyyəsinin müəyyən müddət saxlanmasını yoxlayır. Stress test isə yükü tədricən və ya qəfil artıraraq komponentin yuxarı həddini, doyma nöqtəsini, gecikmənin necə dəyişdiyini və hansı formada sıradan çıxdığını göstərir. Bunlar ayrı suallardır və Shopify hər ikisini istifadə edir.
Test trafikinin şəkli də production-a bənzəməlidir. Shopify-ın miqyaslı test prosesində flash sale üçün ayrıca axın var: storefront aktivliyi qəfil artır və simulyasiya edilən istifadəçilər eyni məhsulu almağa çalışırlar. Başqa axınlar gəzinmə, admin əməliyyatları və Storefront API trafikini təkrarlayır. Beləcə bir “orta request” rəqəmi müxtəlif bottleneck-ləri gizlətmir.
Sintetik test yenə production-un surəti deyil. Real istifadəçi retry edir, botlar fərqli davranır, payment provider gecikə bilər, cache hit nisbəti dəyişir. Buna görə testdən çıxan ən qiymətli məlumat rekord throughput yox, sistemin əyilməyə başladığı nöqtədir: hansı queue böyüyür, p95 latency nə vaxt sıçrayır, error budget harada sürətlə xərclənir və overload zamanı hansı funksiya əvvəl məhdudlaşdırılmalıdır.
Flash sale üçün dayanıqlı dizayn bir “sehrli” komponentdən yaranmır. Shopify nümunəsində əsas fikir qatların birlikdə işləməsidir: routing request-i doğru pod-a bağlayır, pod nasazlıq və yük sərhədi yaradır, cache bahalı oxumaları azaldır, checkout correctness qaydalarını qoruyur, performans testləri isə bütün bu fərziyyələri trafik gəlməzdən əvvəl sıxır.
Tez-tez verilən suallar
Flash sale adi yüksək trafikdən nə ilə fərqlənir?
Trafik qısa müddətdə kəskin artır, çoxlu alıcı eyni mağazaya, məhsula və checkout axınına yönəlir. Bu, orta yükü deyil, konkret resurslardakı sıxlığı kritik edir.
Shopify pod arxitekturasından niyə istifadə edir?
Pod mağazaların bir hissəsini ayrıca datastore dəsti daxilində saxlayır. Beləliklə, yük və nasazlıq bütün platformaya nəzarətsiz yayılmır.
Flash sale üçün yalnız load test kifayətdirmi?
Xeyr. Load test məlum hədəfi yoxlayır, stress test isə sistemin yuxarı həddini və dağılma formasını göstərir. Real trafik forması və bahalı endpoint-lər də sınaqda təkrarlanmalıdır.
Mənbələr
- A Pods Architecture To Allow Shopify To Scale
- Pummelling the Platform, Performance Testing Shopify
- Performance Testing At Scale for BFCM and Beyond
Bu yazı süni intellekt köməyi ilə yazılıb, faktları və mənbələri yoxlanılıb.
Top comments (0)