Redis por VPN parece lento: menos viaxes de ida e volta por petición
Unha VPN non converte unha chamada remota a Redis en local. Orzamente as viaxes por petición, reutilice conexións e manteña as canalizacións lonxe das transaccións.
Unha páxina que responde en 200 ms contra un Redis local tarda catro segundos en canto o cliente se sitúa detrás dunha VPN, mentres os contadores do servidor quedan inactivos. O rexistro lento non mostra nada por riba dun milisegundo, o gráfico de CPU é plano e a instancia atende outros clientes sen queixarse. O que cambiou é a distancia, e o que multiplica a distancia é o número de veces que o seu código se detén e espera. Percorra a ruta da petición desde o cliente cara a fóra e a solución case sempre son menos esperas secuenciais en lugar dun servidor máis rápido.
Comece polo cliente, non polas métricas do servidor
Observe o proceso do cliente entre o primeiro comando e o último. Se a traza mostra unha resposta, unha pausa e despois o seguinte comando, está a pagar unha viaxe completa por comando e ningún axuste do servidor o cambiará. O rexistro lento é o instrumento equivocado aquí, porque rexistra o tempo de execución e exclúe deliberadamente a E/S de comunicación. Un rexistro lento limpo xunto a un endpoint lento é a sinatura dun problema de viaxes de ida e volta.
Mida a ruta mesma antes de tocar o código. redis-cli -h redis.example.internal --latency envía PING repetidos e imprime o tempo medio de petición e resposta, que é o seu custo por intercambio. Multiplíqueo polo número de comandos secuenciais nunha acción de usuario e terá un mínimo para o endpoint.
Conte as viaxes que unha acción de usuario necesita de verdade
Tome un só endpoint e anote cada chamada a Redis en orde, incluídas as que se agochan dentro dun ORM, un middleware de sesión ou unha busca de feature flag. A maioría dos endpoints lentos acaban facendo vinte ou trinta chamadas onde tres abondarían, e as ocultas adoitan ser a maioría.
Unha cadea de dependencias non se pode colapsar: se o segundo comando precisa a clave que devolve o primeiro, a espera é real e as únicas opcións son outro modelo de datos ou unha operación no servidor que exprese todo o paso á vez. As lecturas independentes son outro caso, porque nada lle obriga a esperar a primeira resposta antes de enviar a segunda. Marque cada chamada como dependente ou independente antes de editar nada, e a forma da solución vólvese obvia.
O número que importa son as esperas secuenciais, non os comandos totais. Trinta comandos nun lote seguen custando unha espera.
Agrupe só os comandos que non dependen uns doutros
Unha canalización pon en cola comandos independentes e recolle as respostas en orde, convertendo N esperas nunha. A maioría dos clientes expóñena como bloque, callback ou xestor de contexto en lugar dun modo de conexión aparte, así que comprobe a API que trae a súa versión instalada. A ganancia escala co tempo de viaxe, e por iso mesmo importa nunha VPN e apenas se nota en 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())
Pase transaction=False cando só queira agrupar. Co valor predeterminado o cliente envolve o lote en MULTI e EXEC, o que o fai atómico e cambia o que outros clientes poden observar en voo. A atomicidade é unha decisión de corrección, non un botón de rendemento, e unha canalización non é unha transacción só porque ambas reduzan viaxes.
Lea cada resposta en lugar de só o envío do lote. Un comando en cola pode devolver un erro mentres o lote no seu conxunto se completa, e un cliente que descarta a lista de respostas converte unha escritura fallida nunha silenciosa. Compare a lonxitude da lista de respostas co número de comandos que puxo en cola.
Manteña viva a conexión entre accións
Cada conexión nova paga resolución de nomes, un handshake TCP, un handshake TLS e un AUTH, e por VPN cada un deses é unha viaxe que non pode eliminar agrupando. Cree o cliente unha vez por proceso e reutilíceo, ou use o pool que ofrece a súa biblioteca cun tamaño acoutado. Reconectar por petición é a segunda causa máis común deste síntoma despois das esperas por comando.
Manteña o nome de host privado na configuración en lugar dun enderezo literal. A validación do certificado e a identidade do servizo seguen aplicándose nunha rede privada, e fixar un IP rompe no momento en que o provedor renumera unha subrede. Se a resolución é a parte lenta, arranxe a ruta do resolutor en lugar da cadea de conexión.
Defina un tempo de espera de socket explícito para que un túnel atascado falle rápido en lugar de colgar un traballador. Despois confirme que o pool se reutiliza de verdade rexistrando a creación de conexións no cliente.
Dimensione o lote antes de que se converta nun problema de memoria
Redis retén as respostas en cola durante todo o lote, e o cliente retén despois o resultado analizado. Unha canalización de dez mil valores grandes cambia esperas de rede por picos de memoria e pausas longas nos dous extremos.
Escolla o tamaño do lote segundo o volume de resposta e non o número de comandos. Uns centos de comandos pequenos nun lote adoitan ser cómodos, mentres que cen cargas de varios kilobytes non o son. Divida por bytes e tamén por número, e manteña cada lote dentro do orzamento de latencia que o endpoint ten de verdade.
Mida de extremo a extremo despois do cambio: redis-cli -h redis.example.internal --latency-history mostra se a ruta mesma é estable, e o seu propio temporizador de peticións mostra se o endpoint mellorou. Se o endpoint segue lento mentres o historial de latencia é plano, o custo restante é traballo do servidor ou a súa propia serialización, e o seguinte paso é un perfil do xestor en lugar doutro cambio de agrupación.