VPN üzərindən Redis yavaş görünür: sorğu başına gediş-dönüşləri azaltmaq
VPN uzaq Redis çağırışını yerli çağırışa çevirmir. Hər sorğu üçün gediş-dönüş büdcəsi qurun, bağlantıları təkrar istifadə edin və boru xətlərini tranzaksiyalardan uzaq saxlayın.
Yerli Redis-ə qarşı 200 ms-də cavab verən səhifə, müştəri VPN-in arxasına keçdikdən sonra dörd saniyə çəkir, halbuki server sayğacları boş qalır. Yavaş jurnal bir millisaniyədən yuxarı heç nə göstərmir, CPU qrafiki düzdür və instans başqa müştərilərə şikayətsiz xidmət edir. Dəyişən məsafədir və məsafəni çoxaldan şey kodunuzun dayanıb gözləmə sayıdır. Sorğu yolunu müştəridən bayıra doğru izləyin və həll demək olar ki, həmişə daha sürətli server deyil, daha az ardıcıl gözləmədir.
Server metriklərindən deyil, müştəridən başlayın
Birinci əmrdən sonuncuya qədər müştəri prosesini izləyin. Əgər izləmə cavab, fasilə, sonra növbəti əmr göstərirsə, hər əmr üçün tam gediş-dönüş ödəyirsiniz və serverin heç bir tənzimlənməsi bunu dəyişməyəcək. Yavaş jurnal burada yanlış alətdir, çünki icra vaxtını qeyd edir və kommunikasiya I/O-nu qəsdən istisna edir. Yavaş endpoint-in yanında təmiz yavaş jurnal gediş-dönüş probleminin imzasıdır.
Koda toxunmazdan əvvəl yolun özünü ölçün. redis-cli -h redis.example.internal --latency təkrar PING-lər göndərir və orta sorğu və cavab vaxtını çap edir, bu da hər mübadilə üçün xərcinizdir. Bunu bir istifadəçi hərəkətindəki ardıcıl əmrlərin sayına vurun və endpoint üçün minimum alırsınız.
Bir istifadəçi hərəkətinin həqiqətən tələb etdiyi gediş-dönüşləri sayın
Tək bir endpoint götürün və hər Redis çağırışını sıra ilə yazın, o cümlədən ORM, sessiya middleware-i və ya feature-flag axtarışı içində gizlənənləri. Ən yavaş endpoint-lərin əksəriyyəti üç çağırışın kifayət edəcəyi yerdə iyirmi və ya otuz çağırış edir və gizli olanlar adətən çoxluq təşkil edir.
Asılılıq zəncirini yığmaq mümkün deyil: əgər ikinci əmr birincinin qaytardığı açarı tələb edirsə, gözləmə realdır və yeganə seçimlər fərqli məlumat modeli və ya bütün addımı bir anda ifadə edən server tərəfi əməliyyatıdır. Müstəqil oxumalar fərqli haldır, çünki ikincini göndərməzdən əvvəl birinci cavabı gözləməyə heç nə məcbur etmir. Dəyişiklik etməzdən əvvəl hər çağırışı asılı və ya müstəqil kimi işarələyin və həllin forması aydınlaşacaq.
Əhəmiyyətli rəqəm ümumi əmrlər deyil, ardıcıl gözləmələrdir. Bir partiyada otuz əmr yenə də bir gözləməyə başa gəlir.
Yalnız bir-birindən asılı olmayan əmrləri partiyalayın
Boru xətti müstəqil əmrləri növbəyə qoyur və cavabları sıra ilə toplayır, N gözləməni birinə çevirir. Əksər müştərilər bunu ayrı bağlantı rejimi kimi deyil, blok, callback və ya kontekst meneceri kimi təqdim edir, ona görə quraşdırılmış versiyanızın təqdim etdiyi API-ni yoxlayın. Qazanc gediş-dönüş vaxtı ilə ölçülür, buna görə də VPN-də əhəmiyyətli olur və localhost-da demək olar ki, hiss olunmur.
import redis
r = redis.Redis(host="redis.example.internal", port=6379, socket_timeout=2)
pipe = r.pipeline(transaction=False)
for key in ("user:1001", "user:1002", "user:1003"):
pipe.get(key)
print(pipe.execute())
Yalnız partiyalama istədikdə transaction=False ötürün. Standart halda müştəri partiyanı MULTI və EXEC içinə sarır, bu da onu atomik edir və digər müştərilərin uçuş zamanı nə görə biləcəyini dəyişir. Atomiklik performans düyməsi deyil, düzgünlük qərarıdır və boru xətti yalnız gediş-dönüşləri azaltdığı üçün tranzaksiya olmur.
Yalnız partiya təqdimatını deyil, hər cavabı oxuyun. Növbəyə qoyulmuş əmr partiya bütövlükdə tamamlanarkən xəta qaytara bilər və cavab siyahısını atan müştəri uğursuz yazmanı səssiz yazmaya çevirir. Cavab siyahısının uzunluğunu növbəyə qoyduğunuz əmrlərin sayı ilə müqayisə edin.
Hərəkətlər arasında bağlantını sağ saxlayın
Hər yeni bağlantı ad həlli, TCP əl sıxma, TLS əl sıxma və AUTH üçün ödəyir və VPN üzərində bunların hər biri partiyalaşdıra bilmədiyiniz bir gediş-dönüşdür. Müştərini proses başına bir dəfə yaradın və təkrar istifadə edin və ya kitabxananızın təqdim etdiyi hovuzu məhdud ölçü ilə istifadə edin. Hər sorğu üçün yenidən qoşulma bu simptomun əmr başına gözləmələrdən sonra ikinci ən geniş yayılmış səbəbidir.
Konfiqurasiyada hərfi ünvan deyil, özəl host adını saxlayın. Sertifikat yoxlaması və xidmət kimliyi özəl şəbəkədə də qüvvədədir və IP-ni bərkitmək provayder alt şəbəkəni yenidən nömrələdiyi anda pozulur. Əgər yavaş hissə ad həllidirsə, bağlantı sətrini deyil, həlledici yolunu düzəldin.
Açıq socket timeout təyin edin ki, dayanmış tunel işçini asmaq əvəzinə tez uğursuz olsun. Sonra müştəridə bağlantı yaradılmasını jurnala yazaraq hovuzun həqiqətən təkrar istifadə olunduğunu təsdiqləyin.
Partiya yaddaş probleminə çevrilməzdən əvvəl ölçüsünü müəyyənləşdirin
Redis növbəyə qoyulmuş cavabları partiya müddətində saxlayır, müştəri isə sonra emal edilmiş nəticəni saxlayır. On min böyük dəyərdən ibarət boru xətti şəbəkə gözləmələrini yaddaş sıçrayışları və hər iki tərəfdə uzun fasilələrlə dəyişir.
Partiya ölçüsünü əmrlərin sayına deyil, cavab həcminə görə seçin. Bir partiyada bir neçə yüz kiçik əmr adətən rahatdır, yüz çoxkilobaytlıq yük isə deyil. Həm bayt, həm də say üzrə bölün və hər partiyanı endpoint-in həqiqətən malik olduğu gecikmə büdcəsi içində saxlayın.
Dəyişiklikdən sonra ucdan-uca ölçün: redis-cli -h redis.example.internal --latency-history yolun özünün sabit olub-olmadığını göstərir, öz sorğu taymeriniz isə endpoint-in yaxşılaşdığını göstərir. Əgər gecikmə tarixçəsi düz olduğu halda endpoint hələ də yavaşdırsa, qalan xərc server tərəfindəki iş və ya öz serializasiyanızdır və növbəti addım başqa bir partiyalama dəyişikliyi deyil, handler-in profili çıxarmaqdır.