Power Node Redis7 Notes - Capítulo 7 Redis Cache

7 Cache Redis

7.1 Cliente Jedi

7.1.1 Introdução aos Jedis

Jedis é uma ferramenta de conexão de cliente Redis baseada em java projetada para melhorar o desempenho e a facilidade de uso.

7.1.2 Criar um projeto

Primeiro, crie um projeto Maven comum 01-jedis e, em seguida, adicione as dependências Jedis e Junit no arquivo POM.

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
    <!--jedis依赖-->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>4.2.0</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
</dependencies>

7.1.3 Usando instâncias Jedis

O Jedis é basicamente muito simples de usar e fornece um método muito rico de operação do Redis, e esses nomes de método são quase iguais aos comandos do Redis. Você pode criar diretamente uma instância do Jedis toda vez que usá-la. Após a criação da instância do Jedis, a camada inferior do Jedis realmente criará uma conexão Socket para o servidor Redis especificado. Portanto, para economizar recursos do sistema e largura de banda da rede, após cada uso da instância Jedis, o método close() precisa ser chamado imediatamente para fechar a conexão.
Primeiro, você precisa criar a classe de teste JedisTest em src/test/java do projeto.

7.1.3.1 Teste com valor como String

7.1.3.2 Teste com valor como Hash

7.1.3.3 Teste com valor conforme Lista

7.1.3.4 Teste com valor definido

7.1.3.5 Teste com valor como ZSet

7.1.4 Usando o JedisPool

Se o aplicativo criar e destruir instâncias de Jedis com muita frequência, embora os recursos do sistema e a largura de banda da rede sejam salvos, o desempenho do sistema será bastante reduzido. Porque criar e destruir conexões Socket é demorado. Neste ponto, você pode usar o pool de conexão Jedis para resolver esse problema.
A diferença entre usar JedisPool e usar uma instância Jedis é que JedisPool é global, e a classe inteira só precisa ser criada uma vez, e toda vez que você precisar operar o Redis, você só precisa tirar uma instância Jedis do JedisPool e usar isso diretamente. Após o uso, não há necessidade de liberar a instância Jedis, basta retornar o JedisPool.

7.1.5 Usando JedisPooled

É complicado usar o bloco try-with-resource para cada operação no Redis, mas usar o JedisPooled não precisa usar essa estrutura para liberar recursos automaticamente.

7.1.6 Conectar Cluster de Alta Disponibilidade do Sentinel

Para conexões com clusters de alta disponibilidade do Sentinel, use JedisSentinelPool diretamente. No cliente, basta registrar os nomes de todos os nós do Sentinel e do Mestre que eles monitoram, sem nenhuma informação de endereço do mestre-escravo. Ele também usa JedisPool, e os Jedis usados ​​também precisam retorná-lo ao pool de conexão por meio do método close().

7.1.7 Conectando sistemas distribuídos

Para a conexão do sistema distribuído Redis, você pode usar diretamente o JedisCluster. A camada inferior também usa a tecnologia de pool de conexão Jedis. Após cada uso, não há necessidade de fechá-lo explicitamente, ele será fechado automaticamente.
Existem dois construtores comumente usados ​​para JedisCluster. Um é um construtor que precisa apenas de um nó de cluster. Esse nó pode ser qualquer nó do cluster. Enquanto o nó estiver conectado, todo o cluster estará conectado. Mas existe um risco nesse construtor: o nó especificado por ele fica inativo pouco antes da conexão, então o cliente não conseguirá se conectar ao cluster. Portanto, é recomendável usar o segundo construtor, que lista todos os nós do cluster. Isso evitará esse risco.

7.1.8 Transações Operacionais

Para a operação de transações do Redis, o Jedis fornece os métodos multi(), watch() e unwatch() para corresponder aos comandos multi, watch e unwatch no Redis. O método multi() de Jedis retorna um objeto Transaction, e seus métodos exec() e discard() são usados ​​para executar e cancelar a execução da transação.

7.1.8.1 Lançando exceções Java


A saída é o resultado de todas as reversões.

7.1.8.2 Fazer exceção Redis


Sua saída é o valor modificado. Isso significa que a exceção lançada pelo tempo de execução do Redis não será capturada pelo código Java e não afetará a execução do código Java.

7.1.8.3 vigiar()

7.2 Plataforma de negociação de produtos financeiros

7.2.1 Spring Boot integra Redis

7.2.2 Modelo de operação do Redis

No Spring Boot, você pode usar diretamente o Jedis para implementar a operação do Redis, mas geralmente não é usado dessa maneira. Em vez disso, use a instância da classe RedisTemplate do modelo de operação do Redis para operar o Redis.
A classe RedisTemplate é uma classe de modelo que opera no Redis. Existem muitos métodos nesta classe de modelo e muitos desses métodos têm o mesmo nome ou são semelhantes ao comando de operação do Redis. Por exemplo, delete(), keys(), scan() e multi(), exec(), discard(), watch(), etc. Claro, existem dois tipos de métodos boundXxxOps(k) e opsForXxx() para obter instâncias de operação que operam em vários tipos de Value.

7.2.3 Requisitos

Vamos usar um exemplo para ilustrar como o Spring Boot se integra ao Redis.
Para uma plataforma de negociação de produtos financeiros experiente e madura, a página inicial do usuário final geralmente exibe uma lista de seus produtos financeiros mais recentes e, ao mesmo tempo, fornece aos usuários uma função de consulta de produtos. Além disso, para mostrar a força e a reputação da plataforma, o volume total de transações e o número de usuários registrados concluídos pela plataforma também serão exibidos em uma posição bem visível na página inicial da plataforma. No lado do gerenciamento, os administradores podem modificar produtos, colocar novos produtos nas prateleiras e remover produtos antigos por meio da página de gerenciamento.
Para facilitar o entendimento do processo de integração do Redis e do Spring Boot, o sistema é simplificado aqui: a página inicial do cliente disponibiliza apenas consultas com base no nome do produto financeiro, e apenas o valor total da transação é exibido em posição de destaque . O terminal de gestão realiza apenas a função de colocar novos produtos nas prateleiras.

7.2.4 Criar projeto SSM

7.2.4.1 Criar um projeto

Defina um projeto Spring Boot e nomeie-o como ssm.

7.2.4.2 Definir o arquivo pom

Muitas dependências, como driver MySQL e Druid, precisam ser importadas no arquivo pom. O conteúdo importante no arquivo POM é o seguinte:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

   <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.3.2</version>
    </dependency>

   <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.12</version>
    </dependency>    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
    </dependency>    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <resources>        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>        <resource>
            <directory>src/main/webapp</directory>
            <targetPath>META-INF/resources</targetPath>
            <includes>
                <include>**/*.*</include>
            </includes>
        </resource>
    </resources>
</build>

7.2.4.3 Modifique o arquivo de configuração principal

Configure MyBatis, Spring, logs e outras configurações no arquivo de configuração principal:

7.2.4.4 Classe de entidade Produto

O valor total de transações na plataforma, ou seja, a soma do “valor total de produtos arrecadados” cuja “data final de solicitação do produto” seja menor que a “data atual de consulta”.

7.2.4.5 Criar tabela de banco de dados

Crie uma tabela chamada product no banco de dados de teste. O arquivo sql criado é o seguinte, basta executar o arquivo diretamente.

DROP TABLE IF EXISTS `product`;CREATE TABLE `product` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `rate` double DEFAULT NULL,
  `amount` double DEFAULT NULL,
  `raised` double DEFAULT NULL,
  `cycle` int(11) DEFAULT NULL,
  `endTime` char(10) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

INSERT INTO `product` VALUES (1,'天鑫添益2',2.76,50000,20000,30,'2022-07-10'),(2,'国泰添益',2.86,30000,30000,60,'2022-07-12'),(3,'国泰高鑫',2.55,60000,50000,90,'2022-07-09'),(4,'国福民安',2.96,30000,20000,7,'2022-05-10'),(5,'天益鑫多',2.65,80000,60000,20,'2022-07-05'),(6,'惠农收益',3.05,30000,20000,10,'2022-06-10'),(7,'惠农三鑫',2.76,50000,30000,30,'2022-07-02'),(8,'励学收益',2.86,30000,20000,20,'2022-07-11');

7.2.4.6 Definir index.jsp

Crie um diretório webapp em src/main para armazenar arquivos jsp. Este é um diretório comum, não há necessidade de executar Mark Directory As. Crie um arquivo index.jsp no diretório webapp.

7.2.4.7 Definir manager.jsp

Crie um subdiretório jsp no diretório webapp e defina manager.jsp nele.

7.2.4.8 Definir result.jsp

Defina result.jsp em webapp/jsp.

7.2.4.9 ProductController类

7.2.4.9.1 indexHandle()

7.2.4.9.2 registrarHandle()

7.2.4.9.3 listaHandle()

7.2.4.10 Interface ProdutoServiço

7.2.4.11 ProductServiceImpl类

7.2.4.11.1 salvarProduto()

7.2.4.11.2 Três métodos find

7.2.4.12 interface ProductDao

7.2.4.13 Mapeamento de arquivos

7.2.4.14 Classe de inicialização do aplicativo

7.2.5 Criar projeto SSRM

7.2.5.1 Criar um projeto

Copie o projeto ssm e renomeie-o para springboot-redis.

7.2.5.2 Modificar arquivo pom

Adicione dependências de integração Spring Boot e Redis no arquivo pom.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

7.2.5.3 Modificar arquivo de configuração

Adicione Redis e configurações relacionadas ao cache ao arquivo de configuração.

7.2.5.4 Modifique a classe de entidade Produto

Como o objeto de classe de entidade consultado deve ser armazenado em cache no Redis, o Redis exige que a classe de entidade seja serializada. Portanto, a classe de entidade precisa implementar a interface de serialização.

7.2.5.5 Modifique a classe ProductServiceImpl

7.2.5.5.1 Modificar saveProduct()


@CacheEvict é usado para limpar os dados em cache no espaço de cache especificado por valor. allEntries é true para especificar a limpeza de todos os dados no espaço do cache. Se você não deseja limpar tudo, precisa especificar os dados-chave a serem limpos por meio do atributo chave.

7.2.5.5.2 Modifique os dois métodos find


@Cacheable é usado para especificar que o resultado da consulta é armazenado em cache no espaço de cache especificado usando a chave especificada. Se houver outro acesso aos dados da consulta, ele será verificado primeiro no cache.

7.2.5.5.3 Modificar findTurnover()

7.2.5.6 Modifique a classe de inicialização do aplicativo

@EnableCaching用于开启当前应用的缓存功能。

7.2.6 Resumo

Como integrar o Spring Boot com o Redis?

  • Importar dependências no POM
  • Registre as informações de conexão do Redis e as informações de cache no arquivo de configuração
  • As classes de entidade que precisam ser armazenadas em cache no Redis devem ser serializadas
  • A anotação @EnableCaching deve ser adicionada à classe de inicialização do Spring Boot
  • A anotação @Cacheable deve ser adicionada ao método de consulta
  • Adicione a anotação @CacheEvict ao método de gravação de dados
  • Para métodos que requerem operação manual do Redis, o objeto de operação precisa ser obtido por meio do RedisTemplate

7.3 Problemas de alta simultaneidade

Embora o cache do Redis reduza a pressão no DBMS e reduza o RT, vários problemas podem ocorrer em situações de alta simultaneidade.

7.3.1 Penetração de cache

Quando os dados acessados ​​pelo usuário não estão no cache nem no banco de dados, cada consulta do usuário "penetra" no cache "diretamente" no banco de dados. Essa situação é chamada de penetração de cache. Quando chegam solicitações de acesso altamente frequentes, a penetração do cache não apenas aumenta o tempo de resposta, mas também aciona consultas altamente simultâneas ao DBMS, o que pode causar a falha do DBMS.
Há dois motivos principais para a penetração do cache: um é que não há resultado de consulta correspondente no banco de dados e o outro é que o resultado da consulta não é armazenado em cache quando o resultado da consulta está vazio. Portanto, para os dois pontos acima, existem duas soluções:

  • Limitar solicitações ilegais
  • Dê um valor padrão para consultas com resultados vazios

7.3.2 Decomposição do buffer

Para uma cache, se o seu volume de acesso for particularmente grande em condições de alta simultaneidade, quando o tempo limite efetivo da cache for atingido, pode haver um grande número de acessos para reconstruir a cache, ou seja, essas solicitações de acesso descobrem que não há nenhum desses dados no cache, então vá imediatamente para o DBMS para consultar, então isso pode causar altas consultas simultâneas ao DBMS, o que levará diretamente ao colapso do DBMS. Essa situação é chamada de quebra de cache e os dados armazenados em cache são chamados de dados quentes.
Para a solução de quebra de cache, é comum usar o mecanismo de "bloqueio de detecção dupla".

7.3.3 Cache Avalanche

Para os dados no cache, muitos deles têm um tempo de expiração. Se o tempo de expiração de um grande número de caches chegar quase simultaneamente no mesmo período de tempo muito curto, isso pode causar altas consultas simultâneas ao DBMS em um cenário de alto acesso simultâneo, o que pode levar diretamente ao colapso do DBMS. Essa situação é chamada de avalanche de cache.
Não existe uma solução direta para a avalanche de cache, a melhor solução é a prevenção, ou seja, planejar com antecedência o tempo de expiração do cache. Torne o cache permanentemente válido e limpe o cache correspondente quando os dados no banco de dados forem alterados. Se o DBMS adotar uma implantação distribuída, os dados do ponto de acesso serão distribuídos uniformemente entre os diferentes nós do banco de dados para equilibrar as possíveis cargas de acesso de entrada.

7.3.4 Inconsistência de gravação dupla no cache do banco de dados

As três situações acima são para problemas que podem ocorrer em cenários de leitura de alta simultaneidade, enquanto o problema de inconsistência de gravação dupla no cache do banco de dados é um problema que pode ocorrer em cenários de gravação de alta simultaneidade.
Para o problema de inconsistência de gravação dupla no cache do banco de dados, pode ocorrer nos dois cenários a seguir:

7.3.4.1 Cenário "Modificar cache de atualização do banco de dados"

Para um sistema com uma função de aquecimento de cache, as alterações nos dados comumente usados ​​no DBMS causarão atualizações nos dados relevantes no cache. No cenário de altas solicitações de gravação simultâneas, se várias solicitações modificarem os mesmos dados no DBMS e, após a modificação, os dados relacionados no cache precisarem ser atualizados, pode haver inconsistências entre o cache e os dados no banco de dados.

7.3.4.2 Cenário "Modificar cache de exclusão do banco de dados"

Em muitos sistemas, não há função de aquecimento do cache. Para manter a consistência entre o cache e os dados do banco de dados, o cache correspondente geralmente é excluído após a gravação do banco de dados.
No cenário de solicitações de leitura e gravação simultâneas, se essas solicitações incluírem operações de gravação e leitura nos mesmos dados no DBMS e, após a modificação, os dados relevantes no cache devem ser excluídos, pode haver inconsistências entre o cache e os dados no banco de dados Case.

7.3.4.3 Solução: exclusão dupla atrasada

A solução de exclusão dupla atrasada é uma solução específica para o cenário de "modificar o banco de dados e excluir o cache". No entanto, esta solução não pode resolver completamente a situação de inconsistência de dados, ela pode apenas reduzir a probabilidade de inconsistência de dados.
O esquema de exclusão dupla atrasada significa que uma operação de exclusão de cache será executada imediatamente após a conclusão da operação de gravação e, em seguida, o cache será excluído após parar por um período de tempo (geralmente alguns segundos). O intervalo entre duas exclusões é maior que a duração de uma operação de gravação em cache.

7.3.4.4 Solução: Filas

Nos dois cenários acima, apenas os dados no banco de dados e no cache serão inconsistentes, principalmente devido ao processamento paralelo de solicitações. Desde que as solicitações sejam gravadas em uma fila unificada, a próxima solicitação só pode ser processada após o processamento de uma solicitação. Mesmo que o sistema serialize o processamento das solicitações do usuário, o problema de inconsistência de dados pode ser completamente resolvido.

7.3.4.5 Solução: bloqueio distribuído

Embora a serialização da fila possa resolver a inconsistência de dados entre o banco de dados e o cache, o sistema perde simultaneidade e reduz o desempenho. O uso de bloqueios distribuídos pode coordenar o relacionamento entre os threads de processamento sem afetar a simultaneidade, para que os dados no banco de dados e no cache possam atingir a consistência.
Só é necessário coordenar o acesso aos dados compartilhados no banco de dados por meio de bloqueios distribuídos.

Acho que você gosta

Origin blog.csdn.net/f5465245/article/details/130969078
Recomendado
Clasificación