Grande número de conexões (Valkey e Redis OSS) - Amazon ElastiCache

Grande número de conexões (Valkey e Redis OSS)

Caches de tecnologia sem servidor e nós individuais do ElastiCache (Redis OSS) dão suporte a até 65 mil conexões de cliente simultâneas. No entanto, para otimizar o desempenho, recomendamos que as aplicações cliente não funcionem de maneira constante nesse nível de conexões. O Valkey e o Redis OSS têm um processo de thread único baseado em um loop de eventos no qual as solicitações de cliente recebidas são processadas sequencialmente. Isso significa que o tempo de resposta de um determinado cliente aumenta à medida que o número de clientes conectados aumenta.

É possível realizar o seguinte conjunto de ações para evitar um gargalo de conexões em um servidor Valkey ou Redis OSS:

  • Realize operações de leitura a partir das réplicas de leitura. Isso pode ser feito usando-se os endpoints de leitor do ElastiCache em modo cluster desabilitado ou usando réplicas para leituras em modo de cluster habilitado, inclusive um cache sem servidor.

  • Distribua tráfego de gravação em vários nós primários. É possível fazer isso de duas maneiras. É possível usar um cluster multifragmentado do Valkey ou Redis OSS com um cliente compatível com o modo cluster. Também é possível gravar em vários nós primários em modo de cluster desabilitado com fragmentação do lado do cliente. Isso é feito automaticamente em um cache sem servidor.

  • Use um pool de conexões quando disponível na biblioteca cliente.

Em geral, criar uma conexão TCP é uma operação cara em termos computacionais em comparação com os comandos típicos do Valkey ou Redis OSS. Por exemplo, lidar com uma solicitação SET/GET é uma ordem de magnitude mais rápida ao reutilizar uma conexão existente. O uso de um pool de conexões de clientes com um tamanho finito reduz a sobrecarga do gerenciamento de conexões. Isso também limita o número de conexões de entrada simultâneas da aplicação cliente.

O seguinte exemplo de código do PHPRedis mostra que uma nova conexão é criada para cada nova solicitação do usuário:

$redis = new Redis(); if ($redis->connect($HOST, $PORT) != TRUE) { //ERROR: connection failed return; } $redis->set($key, $value); unset($redis); $redis = NULL;

Comparamos esse código em um loop em uma instância do Amazon Elastic Compute Cloud (Amazon EC2) conectada a um nó Graviton2 (m6g.2xlarge) do ElastiCache (Redis OSS). Colocamos o cliente e o servidor na mesma zona de disponibilidade. A latência média de toda a operação foi de 2,82 milissegundos.

Quando atualizamos o código e usamos conexões persistentes e um pool de conexões, a latência média de toda a operação foi de 0,21 milissegundo:

$redis = new Redis(); if ($redis->pconnect($HOST, $PORT) != TRUE) { // ERROR: connection failed return; } $redis->set($key, $value); unset($redis); $redis = NULL;

Configurações de redis.ini necessárias:

  • redis.pconnect.pooling_enabled=1

  • redis.pconnect.connection_limit=10

O seguinte código é um exemplo de um pool de conexões do Redis-py:

conn = Redis(connection_pool=redis.BlockingConnectionPool(host=HOST, max_connections=10)) conn.set(key, value)

O seguinte código é um exemplo de um pool de conexões do Lettuce:

RedisClient client = RedisClient.create(RedisURI.create(HOST, PORT)); GenericObjectPool<StatefulRedisConnection> pool = ConnectionPoolSupport.createGenericObjectPool(() -> client.connect(), new GenericObjectPoolConfig()); pool.setMaxTotal(10); // Configure max connections to 10 try (StatefulRedisConnection connection = pool.borrowObject()) { RedisCommands syncCommands = connection.sync(); syncCommands.set(key, value); }