Redis през VPN изглежда бавен: намаляване на двупосочните обмени на заявка
VPN не превръща отдалеченото извикване на Redis в локално. Планирайте двупосочните обмени за заявка, използвайте повторно връзки и дръжте конвейерите далеч от транзакции.
Страница, която отговаря за 200 ms при локален Redis, отнема четири секунди, след като клиентът се озове зад VPN, докато броячите на сървъра остават празни. Бавният журнал не показва нищо над милисекунда, графиката на CPU е плоска и инстанцията обслужва други клиенти без оплакване. Променило се е разстоянието, а това, което умножава разстоянието, е броят пъти, в които кодът ви спира и чака. Проследете пътя на заявката от клиента навън и решението почти винаги е по-малко последователни изчаквания, а не по-бърз сървър.
Започнете от клиента, а не от метриките на сървъра
Наблюдавайте клиентския процес между първата и последната команда. Ако трасето показва отговор, пауза, а след това следващата команда, плащате пълен двупосочен обмен за всяка команда и никакво настройване на сървъра няма да промени това. Бавният журнал е грешният инструмент тук, защото записва времето за изпълнение и умишлено изключва комуникационния I/O. Чист бавен журнал до бавна крайна точка е подписът на проблем с двупосочните обмени.
Измерете самия път, преди да пипате кода. redis-cli -h redis.example.internal --latency изпраща повтарящи се PING-ове и отпечатва средното време за заявка и отговор, което е вашата цена на обмен. Умножете го по броя последователни команди в едно потребителско действие и получавате долна граница за крайната точка.
Пребройте двупосочните обмени, които едно потребителско действие наистина изисква
Вземете една крайна точка и запишете всяко извикване на Redis по ред, включително скритите в ORM, междинен софтуер за сесии или търсене на флаг за функция. Повечето бавни крайни точки се оказва, че правят двадесет или тридесет извиквания, където три биха стигнали, а скритите обикновено са мнозинството.
Верига от зависимости не може да се свие: ако втората команда се нуждае от ключа, върнат от първата, изчакването е реално и единствените опции са друг модел на данните или сървърна операция, която изразява цялата стъпка наведнъж. Независимите четения са друг случай, защото нищо не ви принуждава да изчакате първия отговор, преди да изпратите втория. Маркирайте всяко извикване като зависимо или независимо, преди да редактирате каквото и да е, и формата на решението става очевидна.
Значещото число са последователните изчаквания, а не общият брой команди. Тридесет команди в една партида все още струват едно изчакване.
Групирайте само командите, които не зависят една от друга
Конвейерът подрежда независими команди на опашка и събира отговорите по ред, превръщайки N изчаквания в едно. Повечето клиенти го предоставят като блок, обратно извикване или контекстен мениджър, а не като отделен режим на връзката, затова проверете API, който доставя инсталираната ви версия. Печалбата се мащабира с времето за двупосочен обмен, което е точно причината да има значение при VPN и едва да се забелязва на localhost.
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())
Подайте transaction=False, когато искате само групиране. При подразбирането клиентът обгръща партидата в MULTI и EXEC, което я прави атомарна и променя какво другите клиенти могат да наблюдават по време на изпълнение. Атомарността е решение за коректност, а не лост за производителност, и конвейерът не е транзакция само защото и двете намаляват двупосочните обмени.
Четете всеки отговор, а не само подаването на партидата. Команда на опашката може да върне грешка, докато партидата като цяло завършва, и клиент, който изхвърля списъка с отговори, превръща неуспешен запис в тих. Сравнете дължината на списъка с отговори с броя команди, които сте поставили на опашка.
Поддържайте връзката жива между действията
Всяка нова връзка плаща за разрешаване на имена, TCP ръкостискане, TLS ръкостискане и AUTH, а през VPN всяко от тях е двупосочен обмен, който не можете да групирате. Създавайте клиента веднъж на процес и го използвайте повторно, или използвайте пула, който библиотеката ви предоставя, с ограничен размер. Повторното свързване за всяка заявка е втората най-честа причина за този симптом след изчакванията на команда.
Дръжте частното име на хост в конфигурацията, а не буквален адрес. Валидирането на сертификата и идентичността на услугата все още важат в частна мрежа, а фиксирането на IP се чупи в момента, в който доставчикът преномерира подмрежа. Ако разрешаването е бавната част, поправете пътя на резолвера, а не низа за връзка.
Задайте явен таймаут на сокета, за да се проваля бързо заседналият тунел, вместо да блокира работник. След това потвърдете, че пулът наистина се използва повторно, като регистрирате създаването на връзки в клиента.
Оразмерете партидата, преди да стане проблем с паметта
Redis държи отговорите на опашката за продължителността на партидата, а клиентът държи анализирания резултат след това. Конвейер от десет хиляди големи стойности разменя мрежови изчаквания за скокове на паметта и дълги паузи в двата края.
Избирайте размера на партидата спрямо обема на отговора, а не броя команди. Няколкостотин малки команди в една партида обикновено са удобни, а сто натоварвания от няколко килобайта не са. Разделяйте по байтове, както и по брой, и дръжте всяка партида в рамките на бюджета за латентност, който крайната точка наистина има.
Измерете от край до край след промяната: redis-cli -h redis.example.internal --latency-history показва дали самият път е стабилен, а вашият собствен таймер за заявки показва дали крайната точка се е подобрила. Ако крайната точка все още е бавна, докато историята на латентността е плоска, остатъчната цена е работа от страна на сървъра или вашата собствена сериализация, а следващата стъпка е профил на обработчика, а не още една промяна в групирането.