Oh meu Deus, é assim que o Redis Pipeline funciona

jogar, problema

Recentemente, o projeto encontrou tal requisito técnico:

O front-end obtém os dados da mensagem do servidor por meio do mecanismo de sondagem longa (http long polling). O servidor precisa assinar as mensagens comerciais de todas as partes comerciais e notificar o front-end.

A sondagem longa, na verdade, significa simplesmente que o front-end inicia uma solicitação http e o servidor suspende a solicitação atual até que expire ou haja algo a ser retornado antes de retornar. O Apollo Configuration Center usa esse mecanismo para implementar notificações de atualização de configuração.

Mas existe tal situação, se o servidor consumir a mensagem, mas a conexão entre o front-end e o servidor for desconectada, a mensagem não poderá ser notificada ao front-end.

Portanto, precisamos salvar as mensagens consumidas pelo servidor para garantir que toda vez que o front-end iniciar uma sondagem longa, os dados da mensagem possam ser obtidos.

Se o front-end puder se inscrever diretamente na fila de mensagens do lado comercial, isso não terá nada a ver com o servidor. Obviamente, isso não é permitido, o front-end não pode se conectar ao nosso middleware de mensagens e os dados da mensagem do lado comercial também precisam ser limpos e processados ​​antes de serem enviados ao front-end.

pensar, planejar

O mecanismo de implementação do Apollo é que todas as configurações são gravadas no banco de dados. Toda vez que uma requisição chega, ela vai para o banco de dados para verificar se há alguma alteração nos dados.

Considerando nosso cenário real de negócios, nossas mensagens comerciais são realmente sensíveis ao tempo, ou seja, se a mensagem expirar, é inútil.

Para considerar o peso leve, a primeira coisa que me vem à mente são as Listas do Redis, que podem ser usadas para implementar as características das filas, então finalmente usarei o Redis como modelo de armazenamento para mensagens.

otimizar, codificar

A estrutura de dados Lists do Redis é uma simples lista vinculada de strings, classificada por ordem de inserção. Os elementos podem ser adicionados na cabeça (esquerda) ou no final (direita).

Usando esse recurso, podemos implementar uma estrutura de dados queue (first-in, first-out) com o comando rpush + lpop ou lpush + rpop .

Mas seja lpop ou rpop , a lista exibirá apenas um dado, que não pode atender às nossas necessidades de obter mais de um de cada vez.

Procurei soluções relevantes na Internet e, em seguida, combinei com a documentação do comando no site oficial.

Uma solução mais viável é desenhada: lrange + ltrim + pipeline

lrange e ltrim são instruções para listas Redis

lrange mylist 0 5

Indica que o elemento é retirado do início da fila (Esquerda), com subscrito 0 e um elemento com subscrito 5. Se for um número negativo, significa que a cauda da fila (Direita) começa a buscar.

ltrim mylist 0 5

O significado de ltrim é manter apenas os elementos do intervalo especificado.O acima significa que apenas os elementos com subscritos 0 - 5 da lista são mantidos e os demais serão excluídos.

Então, se você quiser excluir os primeiros 6 dados, talvez seja necessário escrever:

ltrim mylist 5 -1

Um número negativo significa que a cauda da fila (direita) começa a buscar.

De acordo com a implementação, lrange + ltrim pode obter o efeito de obter vários elementos de List, por que você precisa usar pipeline?

Na verdade, há um problema óbvio de simultaneidade aqui. Esses dois comandos  não são operações atômicas para redis  . Se outros threads excluirem parte dos dados na fila entre os threads que executam esses dois comandos, o segundo Quando o comando for executado, o os dados na lista estão realmente errados.

A função pipeline do Redis pode resolver o problema que mencionamos acima.

A maioria das pessoas pode não estar familiarizada com pipelines, porque raramente são usados ​​nos negócios.

Vamos dar uma olhada na definição de Redis Pipelining

Um servidor de Solicitação/Resposta pode ser implementado para que seja capaz de processar novas solicitações mesmo que o cliente ainda não tenha lido as respostas antigas. Dessa forma, é possível enviar  vários comandos  para o servidor sem esperar pelas respostas e, finalmente, ler as respostas em uma única etapa.

Isso é chamado de pipelining e é uma técnica amplamente utilizada há muitas décadas. Por exemplo, muitas implementações de protocolo POP3 já suportam esse recurso, acelerando drasticamente o processo de download de novos e-mails do servidor.

Resumindo, ele pode suportar que o cliente envie vários comandos ao mesmo tempo.Após o servidor receber esses comandos, eles serão processados ​​em ordem e em uma transação atômica.

Obviamente, a vantagem mais óbvia do Pipelining é melhorar o tempo de resposta da interação entre cliente e servidor. Colocar vários comandos na mesma requisição certamente melhorará a eficiência em relação a cada comando como uma requisição.

PS: Este método é semelhante à ideia de por que quero obter vários dados de lista. Quando a sondagem longa de front-end obtém resultados de dados, ela precisa retornar vários dados.

Sem mais delongas, cole o código de exemplo diretamente:

@Autowired
RedisTemplate<String, Object> redisTemplate;

public void run() throws Exception {
    System.out.println("start......");
    String key = "key:list";
    Integer number = 5;
    // 每次获取5个
    List<Object> objects = redisTemplate.executePipelined(new RedisCallback<Object>() {

        @Override
        public Object doInRedis(RedisConnection connection) throws DataAccessException {
            connection.lRange(key.getBytes(StandardCharsets.UTF_8), 0, number - 1);
            connection.lTrim(key.getBytes(StandardCharsets.UTF_8), number, -1);
            return null;
        }
    });
    System.out.println(Arrays.toString(objects.toArray()));
    System.out.println("end......");
}

redisTemplate fornece dois tipos de métodos:

  • executePipelined(ação RedisCallback)
  • executePipelined(SessionCallback session)

As funções implementadas pelos dois são semelhantes, exceto que SessionCallback é mais amigável que o pacote de RedisCallck, as palavras deste último são de baixo nível e o uso é mais próximo do comando nativo.

 

Acho que você gosta

Origin blog.csdn.net/Trouvailless/article/details/124257648
Recomendado
Clasificación