fbpx

Como otimizar o Redis com JedisPool

Daniella Costa

Como otimizar o Redis com JedisPool

Você adora ler sobre como vários problemas relacionados ao desempenho são rastreados e corrigidos? Em caso afirmativo, aqui está nossa história de como corrigimos os problemas de desempenho do Redis que estávamos enfrentando otimizando o JedisPool. Esperamos que isso o ajude a fortalecer seu ambiente de TI.

Nossos problemas de desempenho do Redis e esforços para encontrar a causa

Um pico no tempo de resposta

O Site24x7 usa estruturas de dados na memória do Redis para reduzir os acessos aos nossos bancos de dados de back-end. Começamos a encontrar picos ocasionais no tempo de resposta do nosso aplicativo. Após investigação, descobrimos que as chamadas de cache do Redis estavam falhando e os servlets começaram a atingir o banco de dados, o que levou a um aumento no tempo de resposta geral do aplicativo. Isso aconteceu aleatoriamente por alguns segundos, depois o aplicativo voltou ao normal com zero falhas do Redis.

Redis BigKeys

Como nosso tráfego para o Redis era quase constante ao longo do dia, descartamos problemas relacionados ao dimensionamento. Em seguida, começamos a monitorar os parâmetros da máquina Redis e descobrimos que sempre que havia uma queda nas conexões Redis, observamos um alerta de CPU alto. Conseguimos então correlacionar o alto uso da CPU com as falhas do Redis, mas o motivo do alto uso da CPU permaneceu um mistério.

Nossas suspeitas apontavam para as BigKeys e comandos com uso intensivo de CPU, como a chave SMEMBERS. A linha de comando do Redis fornece uma opção para verificar as BigKeys (redis-cli –bigkeys) e visualizar a lista de BigKeys com base nos tipos de dados. Como próxima etapa para corrigir o problema, excluímos as BigKeys maiores que 1 MB. Também tentamos usar o Redis Slow Log  para listar todos os comandos que poderiam tornar o sistema lento, mas não havia comandos com uso intensivo de CPU listados. 

Conexões Jedis

Neste momento, ficamos um pouco confusos, pois não conseguimos encontrar BigKeys ou comandos lentos no Slow Log, mas ainda observamos picos de CPU e conexões perdidas. Como a criação de novas conexões é uma operação de E/S intensiva, começamos a observar o padrão de novas conexões. Para nossa surpresa, descobrimos que o número de conexões criadas por segundo era igual ao número de comandos executados. Ficamos surpresos com essa revelação porque já estávamos usando o JedisPool, uma coleção de conexões Jedis reutilizáveis, para reutilizar as conexões e não havíamos alterado nossa configuração do JedisPool.

Após pesquisas adicionais, descobrimos que o JedisPool oferece muitas opções para definir a configuração com base nas necessidades do aplicativo. Mas estávamos usando a configuração padrão. Isso funcionou bem quando tínhamos menos servidores de aplicativos. À medida que ampliamos os servidores de aplicativos, a configuração padrão resultou no uso ineficiente do JedisPool.

O que é Jedi?

Jedis é uma das bibliotecas de cliente Java mais usadas para Redis e também um dos clientes recomendados na lista  oficial de clientes Redis. 

Conexões maxIdle baixas

Por padrão, os valores maxPoolSize e maxIdle relacionados a JedisPool são 8. À medida que nosso produto crescia, precisávamos de mais conexões, então aumentamos maxPoolSize para 150 enquanto maxIdle permaneceu inalterado. Portanto, com essa configuração, o JedisPool pode criar no máximo 150 conexões a qualquer momento. Ainda assim, ele só poderia manter 8 conexões ociosas no pool por vez, e as conexões restantes foram descartadas.

Isso anulou o propósito de usar o JedisPool, pois novas conexões eram criadas a cada segundo. Isso ocorreu em todos os servidores de aplicativos. A criação de conexões aumentou o uso da CPU do Redis, o que, por sua vez, resultou na eliminação das conexões do Redis. Como todos os dedos apontavam para o alto uso de CPU em clusters Redis devido a um alto número de conexões ao Redis por segundo como o principal motivo, nos concentramos na otimização do JedisPool, que pode ser feita ajustando a configuração do JedisPool.

Configuração do JedisPool

A configuração do JedisPool é baseada no GenericObjectPoolConfig do Apache Commons Pool 2. Ao definir o parâmetro GenericObjectPoolConfig para um valor específico, você poderá melhorar o desempenho do Redis. A amostra a seguir mostra como inicializar e usar o JedisPool:

Definir parâmetros adequados para JedisPoolConfig é crucial, pois isso determina como uma nova conexão será criada.

Otimização JedisPool através do ajuste de parâmetros críticos

Ajustar os parâmetros do pool de conexões com base na carga e em outros fatores relacionados ao ambiente é a melhor maneira de obter melhor desempenho e resolver problemas de desempenho. Aqui estão alguns dos parâmetros cruciais que tentamos ajustar:

maxTotal

O parâmetro maxTotal especifica o número máximo de conexões que podem ser criadas a partir do pool a qualquer momento. Como as instâncias Jedis são de thread único, essa configuração afetará as solicitações simultâneas entre seu aplicativo e o Redis.

 O valor padrão é 8, que provavelmente é muito baixo para um aplicativo pesado. Por outro lado, definir um valor alto para esse parâmetro levará à sobrecarga da CPU e da memória. É crucial descobrir o valor maxTotal adequado ao seu ambiente. Aqui estão algumas dicas importantes a serem consideradas ao identificar seu valor maxTotal ideal:

  • Determine o número esperado de conexões simultâneas com o Redis.
  • Concentre-se em um tempo de resposta médio para executar um comando Redis.
  • Defina o número máximo de conexões suportadas por um servidor Redis.

Por padrão, a versão 2.6 do servidor Redis oferece suporte a 10.000 conexões de cliente. O produto do número de instâncias do aplicativo e maxTotal deve sempre ser menor que o número máximo de conexões suportadas pelo Redis.

Vamos considerar o seguinte exemplo:

  • Máximo de conexões de cliente suportadas por um servidor Redis = 10.000
  • Tempo médio de resposta de uma consulta Redis = 2 ms
  • Número esperado de consultas por segundo (QPS) por instância do Redis = 30.000 

O número de consultas Redis tratadas por uma única instância Jedis por segundo é calculado dividindo um segundo pelo tempo de resposta, que neste cenário = 500 (1.000 ms / 2 ms = 500).

O maxTotal necessário é calculado dividindo o QPS esperado pelo número de consultas tratadas por uma única instância Jedis por segundo. Assim, maxTotal = 60 (30.000 / 500).

Este é um valor teórico. Você pode usar uma ferramenta de monitoramento como o APM Insight para obter as métricas mencionadas acima. É bom reservar algumas conexões extras para uma carga imprevisível.

É melhor ter em mente que o número total de conexões reservadas em todas as instâncias não deve exceder o número máximo de conexões suportadas pelo Redis. Por exemplo, se você tiver 100 instâncias, o número total de conexões seria 6.000 (100 * 60), que é menor que 10.000. Considerando que, se você tiver 200 instâncias, o total seria de 12.000 conexões, o que pode fazer com que seus comandos falhem.

maxIdle

O parâmetro maxIdle especifica o número máximo de instâncias Jedis ociosas que serão mantidas no pool sem serem despejadas dele. Este é o número real de conexões exigidas pelo aplicativo. O valor maxTotal inclui o número total de maxIdle mais a conexão excedente necessária para uma carga imprevisível. 

Se o valor de maxIdle for muito pequeno para seu aplicativo, novas conexões Jedis serão criadas com frequência para atender às solicitações. Criar novas conexões com frequência aumentará o uso da CPU do cluster Redis e afetará negativamente o aplicativo. Se o valor for muito grande para seu aplicativo, as conexões reservadas serão desperdiçadas e outras instâncias do aplicativo poderão não obter recursos suficientes para se comunicar com o Redis. 

Ao definir maxIdle com um valor adequado, você pode garantir que maxTotal obtenha o melhor desempenho na maioria dos cenários, pois nenhuma nova conexão será criada quando o tamanho do pool atingir maxIdle.

minIdle

O parâmetro minIdle especifica o número mínimo de conexões inativas que sempre serão mantidas no pool. O valor padrão é zero, o que significa que todas as conexões que estiverem ociosas por um período maior que minEvictableIdleTimeMillis serão despejadas do pool.

Assim, quando a carga aumenta, muitas novas conexões serão criadas, o que pode afetar o desempenho do aplicativo. Podemos evitar isso definindo um valor minIdle mais alto dependendo da carga. Para aplicações com carga flutuante, um mínimo de (maxIdle / 2) deve ser definido, podendo ir até maxIdle.

bloquear quando esgotado

Essa configuração booleana especifica se o cliente deve aguardar uma conexão livre quando o pool estiver esgotado. O valor padrão é verdadeiro. Somente quando o valor blockWhenExhausted for verdadeiro o parâmetro maxWaitMillis será efetivo.

maxWaitMillis

Este parâmetro especifica o tempo máximo que o cliente deve esperar quando nenhuma conexão estiver disponível. Depois disso, uma mensagem de erro de exceção dizendo “Não foi possível obter o recurso do pool” será exibida. Essa configuração terá efeito somente quando blockWhenExhausted  for definido como true. O valor padrão é -1 ms, o que significa que ele aguardará indefinidamente pela conexão do pool. Recomendamos definir o mesmo valor do tempo limite da conexão Jedis.

minEvictableIdleTimeMillis

Este parâmetro especifica a quantidade mínima de tempo que uma conexão pode ficar inativa antes do despejo. O valor padrão é 60 segundos, adequado para a maioria dos aplicativos. Você pode alterar esse valor com base em seu ambiente e carga. 

Os valores fornecidos aqui são adequados para a maioria das aplicações. No entanto, é melhor monitorar o uso real e decidir os valores para esses parâmetros. Você pode depender de qualquer uma das ferramentas de monitoramento gratuitas disponíveis no mercado, como Site24x7 , ou registrar o uso do JedisPool periodicamente para entender a carga e determinar os valores adequados.

Espero que nossas sugestões sejam úteis para você. Adoraríamos ouvir seus comentários. Por favor, assista a este espaço para mais blogs e dicas dos engenheiros do Site24x7.

Você pode experimentar o Site24x7 dentro da sua empresa sem custo algum. Que tal realizar esse teste agora?

Conheça na prática como o Site24x7 pode ajudar você e o seu negócio. Nossos técnicos estão disponíveis para te apresentar a melhor solução de monitoramento em nuvem para sua infraestrutura, conte sempre com o apoio da equipe ACSoftware.

ACSoftware / Figo Software seu Distribuidor e Revenda ManageEngine no Brasil

Fone (11) 4063 1007 – Vendas (11) 4063 9639