Pipeline: pode ser usado em nós para resolver problemas de desempenho do Redis

prefácio

Vejamos primeiro o modelo de interação entre o cliente e o servidor Redis

Pode-se concluir que:

1. Redis é um serviço de solicitação síncrona baseado em uma solicitação e uma resposta

2. O cliente envia o pacote de dados ao servidor e, em seguida, o servidor envia os dados de resposta de volta ao cliente, o que leva um certo tempo. Esse tempo é chamado de tempo de ida e volta RTT (Round Trip Time).

Quando um cliente precisa realizar muitas requisições seguidas, é fácil perceber que o tempo de ida e volta afeta o desempenho do sistema

Por exemplo: se o RTT de tempo de ida e volta for 250ms, mesmo que o servidor Redis possa lidar com 1.000 solicitações por segundo, só podemos lidar com até quatro solicitações por segundo.

O Redis fornece um método Pipeline que pode melhorar o desempenho dos casos de uso acima, veja abaixo.

Modelo de interação do Redis Pipeline

Pode-se ver que o cliente primeiro grava o comando executado no buffer (memória) e, finalmente, envia o Redis de uma só vez.

O pipeline empacota um lote de comandos e os envia ao servidor. O servidor os empacota e os retorna em ordem após a execução, o que reduz o tempo de idas e voltas interativas frequentes e melhora o desempenho.

uso básico

Pipeline pipeline =jedis.pipelined();
// 循环添加 1000个元素
for(int i = 0; i < 1000; i++){
    pipeline.rpush("rediskey", i + "");
        }
//执行 
pipeline.sync()
复制代码

Ainda é muito simples de usar

A essência do Pipeline

Analisamos profundamente o processo de interação de um pedido, a situação real é que é muito complexo

A figura acima é um fluxograma de interação de solicitação completo:

  1. O cliente chama write para gravar a mensagem no buffer de envio alocado pelo kernel do sistema operacional para o soquete.
  2. O kernel do sistema envia o conteúdo do buffer para a placa de rede e o hardware da placa de rede roteia os dados para a placa de rede do servidor
  3. A placa de rede do servidor coloca os dados no buffer de recebimento alocado pelo kernel para o soquete.
  4. O servidor chama read para buscar a mensagem do buffer de recebimento para processamento
  5. O servidor chama write para enviar o conteúdo da resposta para o buffer de envio
  6. O kernel do servidor envia o conteúdo do buffer para a placa de rede do cliente por meio de roteamento
  7. O kernel do cliente coloca os dados da placa de rede no buffer de recebimento.
  8. O cliente chama read para ler dados do buffer

Resumir

Começamos a pensar que a operação de gravação não retornaria até que a outra parte recebesse a mensagem, mas esse não é o caso.

O tempo real de operações de E/S de gravação

A operação de gravação é responsável apenas por gravar dados no buffer de envio do kernel do sistema operacional nativo e depois retornar. O resto é deixado para o kernel do sistema operacional enviar de forma assíncrona os dados para a máquina de destino. Mas se o buffer de envio estiver cheio, você precisará esperar que o buffer libere espaço livre, que é o tempo real da operação de E/S da operação de gravação.

O verdadeiro consumo de tempo das operações de IO de leitura

Começamos a pensar que a operação de leitura estava puxando dados da máquina de destino, mas esse não é o caso. A operação de leitura é responsável apenas por obter os dados do buffer de recebimento do kernel do sistema operacional nativo. Mas se o buffer estiver vazio, você precisará aguardar a chegada dos dados, que é o tempo real da operação de E/S da operação de leitura.

value = redis.get(key) operação leva tempo

Para uma requisição simples como value = redis.get(key), a operação de escrita quase não demora, e ela retorna diretamente para o buffer de envio, enquanto a leitura é mais demorada porque tem que esperar que a mensagem seja roteada através da rede para A mensagem de resposta processada pela máquina de destino pode ser retornada somente quando for enviada de volta ao buffer de leitura do kernel atual.

O consumo de tempo real do pipeline

Para pipelines, as operações de gravação contínuas não consomem muito tempo. Depois disso, a primeira operação de leitura aguardará uma sobrecarga de ida e volta da rede e, em seguida, todas as mensagens de resposta foram enviadas de volta ao buffer de leitura do kernel e as operações de leitura subsequentes são diretamente Você pode obter o resultado do buffer e devolvê-lo instantaneamente.

Vantagens e desvantagens

Vantagens do Pipeline:

Ao empacotar comandos e executá-los ao mesmo tempo, o pipeline pode economizar o tempo de ida e volta gerado pelo processo de conectar -> enviar comandos -> retornar resultados e reduzir o número de chamadas de E/S (alternar entre modo de usuário e modo kernel ).

Desvantagens do Pipeline:

  • O pipeline não pode empacotar muitos comandos em cada lote, porque o método pipeline empacota os comandos e os envia, portanto, o redis deve armazenar em cache os resultados do processamento de todos os comandos antes de processar todos os comandos. Isso tem um consumo de memória.
  • O pipeline não garante a atomicidade. Durante a execução do comando, se um comando estiver anormal, outros comandos continuarão sendo executados. Portanto, se a atomicidade for necessária, o pipeline não é recomendado.
  • O pipeline só pode atuar em um nó Redis por vez (o motivo será explicado abaixo)

Cena aplicável

Alguns sistemas podem ter requisitos de alta confiabilidade. Cada operação precisa saber imediatamente se a operação foi bem-sucedida e se os dados foram gravados para redis. Este cenário não é adequado.

Em alguns sistemas, os dados podem ser gravados no redis em lotes, permitindo uma certa porcentagem de falhas de gravação, então esse cenário pode ser usado. Por exemplo, 10.000 registros entram no redis por vez e 2 podem falhar. Não importa, existe um mecanismo de compensação na fase posterior.

Por exemplo, no cenário de envio de mensagens em massa, se você enviar 10.000 mensagens de uma vez e implementá-lo de acordo com o primeiro modo, levará muito tempo para o cliente responder à solicitação e o atraso será muito longo. Se o cliente solicitar um tempo limite de 5 segundos, uma exceção definitivamente será lançada e os requisitos em tempo real das mensagens de texto em massa não são tão altos, portanto, é melhor usar o pipeline neste momento.

Recomendações

Embora o Pipeline seja fácil de usar, o número de comandos para cada assembly do Pipeline não pode ser descontrolado, caso contrário, a quantidade de dados em um assembly do Pipeline será muito grande, o que aumentará o tempo de espera do cliente por um lado e causará por outro lado, um certo congestionamento de rede. O pipeline de um grande número de comandos é dividido em vários pipelines menores para concluir

Teste de estresse da tubulação

O Redis vem com uma ferramenta de teste de estresse redis-benchmark, que pode ser usada para testes de pipeline.

Dicas: documentação oficial do redis-benchmark: redis.io/topics/benc…

Primeiro, realizamos um teste de estresse em um comando set comum e o QPS é de cerca de 5w/s.

> redis-benchmark -t set -q
SET: 51975.05 requests per second
复制代码

Adicionamos a opção de pipeline -P parâmetro, que indica o número de solicitações paralelas em um único pipeline. Veja abaixo P=2, e o QPS chega a 9w/s.

> redis-benchmark -t set -P 2 -q
SET: 91240.88 requests per second
复制代码

Olhando novamente para P=3, o QPS chega a 10w/s.

SET: 102354.15 requests per second
复制代码

outros problemas

Por que o pipeline só pode funcionar em um nó Redis, ou seja, o pipeline não pode ser usado no modo de cluster?

Sabemos que o espaço de chaves do cluster Redis é dividido em 16.384 slots (slots), e cada nó mestre é responsável por processar parte dos 16.384 slots de hash.

O comando específico redis calculará um slot (slot) de acordo com a chave e, em seguida, executará operações em um nó específico redis de acordo com o slot. Do seguinte modo:

master1(slave1): 0~5460
master2(slave2):5461~10922
master3(slave3):10923~16383
复制代码

O cluster consiste em três nós mestres, dos quais master1 são alocados 0 5460 slots, master2 são alocados 5461 10922 slots e master3 são alocados 10923~16383 slots.

Um pipeline executará vários comandos em lotes, então cada comando precisa operar um slot (CRC16.getSlot(key)) de acordo com a chave e, em seguida, executar o comando em um nó específico de acordo com o slot, ou seja, um a operação de pipeline usará a conexão Redis de vários nós, que atualmente não é compatível

Dicas: Se você não conhece o conhecimento do cluster Redis, pode consultar: redis.io/topics/clus…

Qual é a diferença entre operações de pipeline e em lote, como mget e mset?

mget e mset também são semelhantes aos pipelines, que executam vários comandos ao mesmo tempo e os enviam ao mesmo tempo, economizando tempo da rede.

A comparação é a seguinte:

  • mset, operação mget é uma operação atômica na fila Redis, pipeline não é operação atômica
  • mset, mget opera um comando correspondente a vários pares de valores-chave e pipeline é vários comandos
  • mset, mget é implementado pelo servidor e o pipeline é concluído pelo servidor e pelo cliente

Qual é a diferença entre pipeline e transação?

Os pipelines focam no tempo RTT, enquanto as transações focam na consistência

  • O pipeline é uma solicitação, o servidor executa sequencialmente, retorna uma vez e a transação solicita várias vezes (comando MULTI + outros n comandos + comando EXEC, portanto, pelo menos 2 solicitações), o servidor executa sequencialmente e retorna uma vez.
  • No modo cluster, ao usar pipeline, o slot deve estar correto, caso contrário o servidor retornará um erro de redirecionamento para o slot xxx; ao mesmo tempo, não é recomendável usar transações, pois supõe-se que os comandos em uma transação são executados no Mestre A e também no Mestre B é executado, A é bem-sucedido e B falha por algum motivo, portanto os dados são inconsistentes, o que é semelhante a uma transação distribuída e não pode garantir consistência absoluta.

O Pipeline tem um limite no número de comandos?

Não há limite, mas os comandos empacotados não podem ser muitos, quanto maior o consumo de memória.

Quantos comandos são apropriados para o Pipeline empacotar e executar?

Consulte a documentação oficial do Redis. De acordo com a explicação da documentação oficial, o lote recomendado é de 10k (nota: este é um valor de referência, ajuste-o de acordo com sua situação real de negócios).

Quando o Pipeline for executado em lotes, outros aplicativos não poderão ler e gravar?

O Redis adota um modelo de multiplexação de E/S multicanal e E/S sem bloqueio, portanto, quando o Pipeline grava em lotes, ele não afeta outras operações de leitura dentro de um determinado intervalo.

Finalmente

Compartilhe um artigo técnico prático todos os dias, o que é útil para entrevistas e trabalho

referência:

Site oficial: redis.io/topics/pipe…

Livro: Deep Adventures in Redis: Princípios Fundamentais e Práticas Aplicadas


Autor: Programador Duan Fei
Link: https://juejin.cn/post/7089081484958679077
Fonte: Rare Earth Nuggets
Os direitos autorais pertencem ao autor. Para reimpressões comerciais, favor contatar o autor para autorização, e para reimpressões não comerciais, favor indicar a fonte.

Acho que você gosta

Origin blog.csdn.net/wdjnb/article/details/124459618
Recomendado
Clasificación