Transações e pipelines Redis: garantindo consistência de dados e otimização de desempenho

insira a descrição da imagem aqui

Diretório de artigos

1. Transação Redis

1.1 O que é uma transação Redis

insira a descrição da imagem aqui

No Redis, uma transação é uma coleção de comandos que podem ser executados em um único processo para garantir a atomicidade, consistência, isolamento e durabilidade desses comandos.

1.1.1 Visão geral da transação

As transações Redis são gerenciadas pelos quatro comandos principais a seguir:

Ordem descrever
MULTI Abra uma transação, marcando o início de um bloco de transação.
EXEC Execute todos os comandos na transação.
DESCARTAR Cancela a transação, descartando todos os comandos enfileirados.
ASSISTIR Monitore uma ou mais chaves para um bloqueio otimista.

1.1.2 Características de transação do Redis

As transações Redis têm os seguintes recursos principais:

características da transação descrever
atomicidade Todos os comandos em uma transação são executados ou nenhum. Isso garante que durante a execução da transação não aconteça que alguns comandos sejam bem-sucedidos e outros falhem.
consistência Os comandos da transação serão executados na ordem em que foram adicionados e não serão interrompidos por comandos de outros clientes. Isto garante que as operações na transação sejam executadas na ordem desejada e não serão afetadas por operações simultâneas.
isolamento Durante a execução da transação, a transação é isolada e não será afetada por outras transações. Mesmo que outras transações simultâneas estejam em execução, as operações na transação não serão vistas por outras transações até que a transação seja executada e confirmada.
Persistência Após a execução da transação, a modificação no banco de dados será persistida no disco. Isto garante que as operações da transação não serão perdidas devido a falhas do sistema, garantindo assim a durabilidade dos dados.

Acima estão os conceitos e características básicas das transações Redis, que garantem que as transações executadas no Redis sejam conjuntos de operações confiáveis ​​e consistentes.

insira a descrição da imagem aqui

O gráfico acima representa as inter-relações entre os principais recursos das transações Redis. Esses recursos apoiam-se mutuamente e, juntos, garantem a confiabilidade e a consistência das transações do Redis. A atomicidade garante que todas as operações em uma transação sejam bem-sucedidas ou falhem. A consistência garante que as operações em uma transação sejam executadas em uma ordem específica, sem interferência de outras operações. O isolamento garante que as transações sejam isoladas de outras transações durante a execução e não interfiram umas nas outras. Finalmente, a persistência garante que as modificações feitas após a execução da transação persistirão e não serão perdidas devido a falhas do sistema. Juntas, essas propriedades formam a base para a confiabilidade e estabilidade das transações Redis.

1.2 Usando transações Redis

1.2.1 Iniciando e confirmando uma transação

No Redis, o uso de transações requer as seguintes etapas:

  1. Use MULTIo comando para iniciar uma transação.
  2. Execute comandos que precisam ser executados dentro de uma transação.
  3. Confirme EXECa transação com o comando e execute todos os comandos da transação.

Aqui está um exemplo passo a passo detalhado usando código Java:

// 创建与Redis服务器的连接
Jedis jedis = new Jedis("localhost", 6379);

// 开启事务
Transaction transaction = jedis.multi();

// 执行事务中的命令
transaction.set("key1", "value1");
transaction.set("key2", "value2");

// 提交事务并获取执行结果
List<Object> results = transaction.exec();

No exemplo acima, os dois comandos transaction.set("key1", "value1")e transaction.set("key2", "value2")serão adicionados à fila de transações e, quando transaction.exec()invocados, todos os comandos da transação serão executados juntos. Se ocorrer um erro entre e, a transação será cancelada e o comando não será executado MULTI.EXEC

1.2.2 Comandos de transação

Dentro de uma transação, você pode usar comandos regulares do Redis, como SET, GET, HSET, ZADDetc. Esses comandos são adicionados à fila de transações até que EXECo comando seja executado.

1.2.3 Exemplo de transação

A seguir está um exemplo de código Java para demonstrar comandos comuns do Redis executados em uma transação:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class RedisTransactionCommandsExample {
    
    
    public static void main(String[] args) {
    
    
        Jedis jedis = new Jedis("localhost", 6379);

        // 开启事务
        Transaction transaction = jedis.multi();

        // 执行事务中的命令
        transaction.set("name", "Alice");
        transaction.hset("user:1", "name", "Bob");
        transaction.zadd("scores", 100, "Alice");
        transaction.zadd("scores", 200, "Bob");

        // 提交事务并获取执行结果
        List<Object> results = transaction.exec();

        // 打印执行结果
        for (Object result : results) {
    
    
            System.out.println("Result: " + result);
        }

        // 关闭连接
        jedis.close();
    }
}

No exemplo acima, são usados ​​os comandos e , que são adicionados à fila de transações SET. Quando executado , todos os comandos da transação são executados juntos. Os exemplos aqui são demonstrações simples, você pode adicionar mais comandos conforme necessário para construir transações mais complexas.HSETZADDtransaction.exec()

2. Pipeline Redis

2.1 O que é um pipeline Redis

Redis Pipeline (Pipeline) é uma tecnologia para otimizar as operações do Redis, que permite que vários comandos sejam enviados ao servidor Redis em uma única comunicação, reduzindo significativamente a sobrecarga de comunicação e melhorando o desempenho. O pipeline pode enviar vários comandos ao servidor ao mesmo tempo, sem esperar pela resposta de cada comando, o que permite ao Redis lidar com operações em lote e leitura e gravação de dados em grande escala com mais eficiência.

O diagrama a seguir mostra como funciona o pipeline do Redis:

insira a descrição da imagem aqui

Na figura acima, o cliente (Cliente) envia vários comandos para o servidor Redis (Servidor), e cada comando é representado por Command 1, Command 2etc. Esses comandos são enviados ao servidor de uma só vez, sem esperar uma resposta para cada comando. Depois que o servidor executa todos os comandos, ele responde o resultado ao cliente de uma só vez. Ao mesmo tempo, o método de funcionamento do pipeline Redis é explicado: ao empacotar vários comandos em uma comunicação, a sobrecarga de comunicação de cada comando é reduzida e o desempenho do sistema é melhorado.

Ao usar o pipeline do Redis, o cliente cria um objeto de pipeline, adiciona vários comandos ao pipeline e, em seguida, executa os comandos no pipeline de uma só vez. Finalmente, o cliente pode coletar os resultados da execução de todos os comandos.

2.1.1 Visão geral do pipeline

No Redis, os pipelines são gerenciados com os seguintes comandos:

Ordem descrever
PIPELINE Ative o modo pipeline, que é usado para enviar vários comandos de uma vez.
MULTI Ative o modo de transação, que é usado para executar uma série de comandos no pipeline.
EXEC Confirma transações no pipeline, executa e retorna resultados.

Usando pipelines, você pode enviar vários comandos ao servidor ao mesmo tempo e, em seguida, obter os resultados de execução de todos os comandos por meio de uma comunicação, reduzindo assim a sobrecarga de comunicação de cada comando e melhorando o desempenho do sistema.

2.1.2 Recursos de pipeline do Redis

O uso de pipelines Redis oferece as seguintes vantagens:

  • Reduza a sobrecarga de comunicação: na transmissão de comando comum, cada comando requer comunicação de rede de ida e volta, e o pipeline pode empacotar vários comandos e enviá-los ao servidor ao mesmo tempo, reduzindo significativamente a sobrecarga de comunicação. Isto é especialmente importante para cenários com alta latência de rede, o que melhora efetivamente o desempenho.
  • Maior rendimento: Pipelines permitem que vários comandos sejam executados em uma comunicação, processando assim mais comandos por unidade de tempo. Isso pode melhorar efetivamente o rendimento e a capacidade de resposta do Redis para cenários que precisam processar um grande número de comandos, como processamento de dados em lote e processamento de solicitações simultâneas.

2.2 Usando o pipeline Redis

2.2.1 Comandos de pipeline

Aqui está um exemplo prático que mostra como usar pipelines Redis para executar vários comandos e melhorar o desempenho:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import java.util.List;

public class RedisPipelineExample {
    
    
    public static void main(String[] args) {
    
    
        Jedis jedis = new Jedis("localhost", 6379);

        // 创建管道
        Pipeline pipeline = jedis.pipelined();

        // 向管道中添加命令
        for (int i = 0; i < 10000; i++) {
    
    
            pipeline.set("key" + i, "value" + i);
        }

        // 执行管道中的命令
        List<Object> results = pipeline.syncAndReturnAll();

        // 关闭连接
        jedis.close();
    }
}

No caso acima, um loop foi usado para adicionar 10.000 comandos ao pipeline SET. Ao usar pipes, todos os comandos podem ser enviados ao servidor em uma comunicação, em vez de um por um, o que reduz a sobrecarga de comunicação e melhora o desempenho.

2.2.2 Desempenho de otimização do pipeline

O uso de pipelines do Redis pode melhorar o desempenho, especialmente se vários comandos precisarem ser agrupados em lote. O princípio do pipeline é enviar vários comandos ao servidor de uma só vez e, em seguida, obter os resultados todos de uma vez, o que reduz o número de viagens de ida e volta para comunicação e, portanto, aumenta significativamente o rendimento.

No entanto, há algumas coisas a ter em mente:

  • Pipelines não oferecem suporte a transações e não podem garantir a execução atômica de vários comandos.
  • Ao usar pipelines, a ordem em que os comandos são executados pode não ser consistente com a ordem em que são adicionados, o que precisa ser considerado com base nos requisitos de negócios.
  • Os pipelines não trazem melhorias de desempenho em todos os cenários e precisam ser avaliados com base nas condições reais.

Ao usar pipelines de maneira razoável, as vantagens do Redis no processamento de dados de alto desempenho podem ser maximizadas.

3. Transação vs. pipeline: quando usar qual

3.1 Cenários aplicáveis ​​de transações

As transações podem garantir operações atômicas e consistentes em alguns cenários e são especialmente adequadas para operações comerciais com fortes requisitos de consistência, como operações de pagamento.

3.1.1 Operação de consistência forte

As transações são um mecanismo adequado para operações que exigem forte consistência. Quando vários comandos precisam ser executados atomicamente em uma sequência de operações, as transações podem garantir que esses comandos sejam todos executados ou não sejam executados para manter a consistência dos dados.

No exemplo a seguir, é simulada uma operação de transferência bancária, onde o saldo de uma conta precisa ser debitado e o saldo de outra conta precisa ser aumentado ao mesmo tempo:

Jedis jedis = new Jedis("localhost", 6379);

// 开启事务
Transaction transaction = jedis.multi();

// 扣减账户1余额
transaction.decrBy("account1", 100);

// 增加账户2余额
transaction.incrBy("account2", 100);

// 提交事务并获取执行结果
List<Object> results = transaction.exec();

// 关闭连接
jedis.close();

3.1.2 Requisitos de alta atomicidade

As transações são uma escolha melhor quando o negócio exige que várias operações sejam bem-sucedidas ou falhem. A transação garante que uma série de comandos na transação sejam executados em modo de operação atômica, mantendo assim a consistência dos dados.

3.2 Cenários aplicáveis ​​do pipeline

Pipelines são adequados para cenários que exigem operações em lote e requisitos de alto rendimento. Ao enviar vários comandos ao servidor de uma só vez, a sobrecarga de comunicação pode ser reduzida e o desempenho melhorado.

3.2.1 Operação em lote

As operações em massa podem ser realizadas com eficiência usando pipelines. Por exemplo, quando você precisa adicionar uma grande quantidade de dados ao banco de dados, o uso de pipes pode reduzir o custo de comunicação de cada comando, melhorando bastante a eficiência da operação.

O exemplo a seguir demonstra como usar pipelines para operações de conjunto em massa:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import java.util.List;

public class RedisPipelineBatchExample {
    
    
    public static void main(String[] args) {
    
    
        Jedis jedis = new Jedis("localhost", 6379);
        Pipeline pipeline = jedis.pipelined();

        // 向管道中添加一批设置操作
        for (int i = 0; i < 1000; i++) {
    
    
            pipeline.set("key" + i, "value" + i);
        }

        // 执行管道中的命令
        List<Object> results = pipeline.syncAndReturnAll();

        // 关闭连接
        jedis.close();
    }
}

3.2.2 Requisitos de alto rendimento

Em cenários onde é necessária alta produtividade, os pipelines podem melhorar significativamente o desempenho. Quando vários comandos precisam ser executados em um curto período de tempo, esses comandos podem ser empacotados e enviados usando pipelines, reduzindo o número de viagens de ida e volta para comunicação.

Ao usar pipelines para processamento de dados em larga escala, pode melhorar especialmente a capacidade de processamento do sistema sob condições de alta carga.

4. Estudo de caso: Garantindo a consistência dos dados e a otimização do desempenho do pagamento de pedidos

4.1 Descrição do cenário

Num sistema de shopping online, deparamo-nos com um problema importante: como garantir a consistência dos dados durante o processo de pagamento de pedidos e como otimizar o desempenho das operações de pagamento. Este blog irá mergulhar neste cenário e fornecer uma solução.

4.1.1 Requisitos de pagamento do pedido

Depois que o usuário faz um pedido, a operação de pagamento do pedido precisa ser realizada para garantir a consistência do pagamento e do status do pedido.

4.1.2 Requisitos de Consistência de Dados

Após o pagamento ser bem-sucedido, o status do pedido deverá ser atualizado para pago para manter a consistência dos dados.

4.1.3 Alto pagamento simultâneo

No caso de alta simultaneidade, é necessário garantir o desempenho e a consistência dos dados de pagamento do pedido.

4.2 Use transações Redis para resolver problemas de consistência de dados

4.2.1 A transação realiza o pagamento do pedido

Jedis jedis = new Jedis("localhost", 6379);
Transaction transaction = jedis.multi();

// 扣除用户余额
transaction.decrBy("user:balance:1", orderAmount);

// 更新订单状态为已支付
transaction.hset("order:1", "status", "paid");

List<Object> results = transaction.exec();

No exemplo acima, uma transação Redis é utilizada para garantir que em uma sequência de operação, a dedução do saldo do usuário e a atualização do status do pedido ocorram simultaneamente. Se alguma etapa da transação falhar, toda a transação será revertida, garantindo a consistência dos dados.

4.2.2 Garantia de Consistência de Transações

O uso de transações pode garantir a consistência do saldo do usuário e do status do pedido, seja bem-sucedido ou falho ao mesmo tempo. Desta forma, a exatidão do pagamento e do status do pedido pode ser garantida e possíveis problemas de inconsistência de dados podem ser evitados.

4.3 Usando o pipeline Redis para otimizar o desempenho de pagamento

4.3.1 Pagamento em lote do pipeline

Jedis jedis = new Jedis("localhost", 6379);
Pipeline pipeline = jedis.pipelined();

for (Order order : orders) {
    
    
    pipeline.decrBy("user:balance:" + order.getUserId(), order.getAmount());
    pipeline.hset("order:" + order.getId(), "status", "paid");
}

List<Object> results = pipeline.syncAndReturnAll();

Neste exemplo, um pipeline Redis é usado para processar pagamentos de vários pedidos em lotes. Ao enviar vários comandos ao servidor ao mesmo tempo, a sobrecarga de comunicação pode ser reduzida, o que pode melhorar significativamente o desempenho das operações de pagamento.

4.3.2 Melhoria de desempenho do pipeline

Ao utilizar pipelines, múltiplas operações de pagamento podem ser agrupadas em uma única comunicação, o que reduz o número de viagens de ida e volta de comunicação, melhorando assim o desempenho do pagamento. Especialmente em cenários com altos pagamentos simultâneos, os pipelines podem reduzir significativamente a carga do servidor e melhorar a capacidade de resposta do sistema.

5. Restrições e precauções para transações e pipelines

5.1 Restrições às transações

As seguintes restrições precisam ser observadas durante o uso de transações, incluindo o uso de comandos WATCH e bloqueios otimistas.

5.1.1 Comando ASSISTIR

O uso do comando WATCH em uma transação pode monitorar uma ou mais chaves. Se a chave monitorada for modificada por outros clientes durante a execução da transação, a transação será interrompida. Isso é para garantir a consistência transacional e evitar condições de corrida.

Exemplo positivo:

Jedis jedis = new Jedis("localhost", 6379);
Transaction transaction = jedis.multi();

// 监视键"balance"
transaction.watch("balance");

// ... 在此期间可能有其他客户端修改了"balance"键的值 ...

// 执行事务
List<Object> results = transaction.exec();

contra-argumento:

Jedis jedis = new Jedis("localhost", 6379);
Transaction transaction = jedis.multi();

// 监视键"balance"
transaction.watch("balance");

// ... 在此期间其他客户端修改了"balance"键的值 ...

// 尝试执行事务,但由于"balance"键被修改,事务会被中断
List<Object> results = transaction.exec();

5.1.2 Bloqueio otimista

Ao lidar com atualizações simultâneas, o bloqueio otimista pode ser usado. Utilizando mecanismos como números de versão ou carimbos de data/hora, verifique se os dados foram modificados por outros clientes antes de executar comandos, evitando assim conflitos de simultaneidade.

Exemplo positivo:

Jedis jedis = new Jedis("localhost", 6379);

// 获取当前版本号
long currentVersion = Long.parseLong(jedis.get("version"));

// 更新数据前检查版本号
if (currentVersion == Long.parseLong(jedis.get("version"))) {
    
    
    Transaction transaction = jedis.multi();
    transaction.set("data", "new value");
    transaction.incr("version");
    List<Object> results = transaction.exec();
} else {
    
    
    // 数据已被其他客户端修改,需要处理冲突
}

5.2 Precauções para tubulação

Ao usar pipelines, você precisa prestar atenção aos seguintes itens, incluindo a serialização e o uso cuidadoso de pipelines.

5.2.1 Não suporta transações

Os pipelines não suportam transações, portanto a atomicidade e a consistência das transações não podem ser alcançadas por meio de pipelines. Se o suporte a transações for necessário, o mecanismo de transação Redis deverá ser usado.

5.2.2 Use tubos com cautela

Embora o pipeline possa melhorar o desempenho, ele não traz melhoria de desempenho em todos os cenários. Em alguns casos, devido à natureza serial do pipeline, determinados comandos podem bloquear a execução de outros comandos, degradando o desempenho.

Exemplo positivo:

Jedis jedis = new Jedis("localhost", 6379);
Pipeline pipeline = jedis.pipelined();

for (int i = 0; i < 1000; i++) {
    
    
    pipeline.set("key" + i, "value" + i);
}

// 执行管道中的命令并获取结果
List<Object> results = pipeline.syncAndReturnAll();

contra-argumento:

Jedis jedis = new Jedis("localhost", 6379);
Pipeline pipeline = jedis.pipelined();

for (int i = 0; i < 1000; i++) {
    
    
    // 注意:此处执行了耗时的命令,可能阻塞其他命令的执行
    pipeline.get("key" + i);
}

// 执行管道中的命令并获取结果
List<Object> results = pipeline.syncAndReturnAll();

6. Resumo

Este blog se aprofunda nos mecanismos de transação e pipeline no Redis e em sua aplicação para garantir a consistência dos dados e otimizar o desempenho. Através de explicações detalhadas e exemplos de códigos, entendemos os conceitos básicos, características, métodos de utilização e cenários aplicáveis ​​de transações e pipelines. A seguir está um resumo do conteúdo principal deste blog:

Na primeira parte, transação Redis , entendemos o conceito e as características da transação. As transações podem garantir a atomicidade, consistência, isolamento e durabilidade de uma série de comandos. Através dos comandos MULTI, EXEC, DISCARD e WATCH, podemos gerenciar o início, confirmação, reversão de transações e monitorar alterações importantes. As transações são adequadas para operações que exigem atomicidade e consistência, especialmente em cenários com fortes requisitos de consistência.

Na segunda parte, pipeline Redis , temos um conhecimento profundo do conceito e das vantagens do pipeline. Os pipelines permitem o envio de vários comandos ao servidor de uma só vez, reduzindo a sobrecarga de comunicação e melhorando o desempenho. Através dos comandos PIPELINE, MULTI e EXEC, podemos criar pipelines, adicionar comandos e executar comandos no pipeline. Os pipelines são adequados para cenários com muitas operações em lote e altos requisitos de rendimento e podem melhorar significativamente o desempenho do Redis.

Em três, transação versus pipeline: quando usar qual parte, comparamos os cenários aplicáveis ​​de transação e pipeline. As transações são adequadas para cenários que garantem operações de forte consistência e altos requisitos de atomicidade, enquanto os pipelines são adequados para cenários com operações em lote e alto rendimento. Através de exemplos, ilustramos como escolher o mecanismo apropriado com base nas necessidades do negócio para atender às necessidades de consistência e desempenho.

Na parte 4. Estudo de Caso: Garantindo Consistência de Dados e Otimização de Desempenho de Pagamento de Pedidos , aplicamos conhecimentos prévios para resolver um problema prático. Mostramos como usar transações para garantir a consistência dos dados para pagamentos de pedidos e como usar pipelines para otimizar o desempenho das operações de pagamento. Este caso reflete totalmente a aplicação de transações e pipelines nos negócios reais.

Na seção Cinco, Restrições e Precauções de Transações e Pipelines , apontamos algumas limitações e cuidados de transações e pipelines. As transações são limitadas por comandos WATCH e bloqueios otimistas, enquanto os pipelines não suportam transações, e o impacto no desempenho precisa ser cuidadosamente considerado ao usá-los.

Neste blog, discutimos detalhadamente os mecanismos de transação e pipeline no Redis e aprendemos como eles podem garantir a consistência dos dados e otimizar o desempenho em aplicações práticas. Seja enfatizando a consistência ou buscando o desempenho, você pode escolher o mecanismo adequado de acordo com as necessidades do negócio para alcançar os melhores resultados.

insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/weixin_46780832/article/details/132415474
Recomendado
Clasificación