O que você sabe sobre o cache Mybatis?

Como o cache é implementado

  • Cache de nível 1

  • Cache secundário

Prática de caso

1. Cache de nível 1

Cache local HashMap baseado em PerpetualCache (mybatis implementa internamente a interface de cache), e seu escopo de armazenamento é Sessão. Após a liberação ou fechamento da Sessão, todos os Caches na Sessão serão esvaziados;

2. Cache secundário

O mecanismo do cache de primeiro nível é o mesmo, o padrão também é o armazenamento HashMap do PerpetualCache, a diferença é que seu escopo de armazenamento é Mapper (Namespace), e a fonte de armazenamento pode ser customizada, como Ehcache;

Para o mecanismo de atualização de dados de cache, quando uma operação C / R / U / D é executada em um determinado escopo (Sessão de cache de primeiro nível / Namespaces de cache de segundo nível), todos os caches selecionados neste escopo serão limpos por padrão.

Se o segundo cache estiver habilitado, primeiro consulte os dados do segundo cache, se o segundo cache os tiver, obtenha os dados do segundo cache, se o segundo cache não estiver, verifique se há dados de cache do primeiro cache, se o primeiro cache não consulta o banco de dados .

3. Limitações do cache secundário

O cache de segundo nível Mybatis não é bom para o cache de nível de dados refinado. Para o cache de mais partes de dados ao mesmo tempo, como os seguintes requisitos: cache de informações do produto, devido ao grande número de visitas a consultas de informações do produto, mas os usuários são obrigados a fazer isso todas as vezes. Pode consultar as informações mais recentes do produto. Neste momento, se você usar o cache de segundo nível do mybatis, não poderá atualizar apenas as informações em cache do produto e não as informações de outros produtos quando um produto muda , porque a área de cache de segundo nível de mybaits é baseada no mapeador. Divisão, quando as informações de um produto são alteradas, todos os dados em cache das informações do produto serão apagados

4. Cache de nível 1 (ativado por padrão)

Mybatis fornece cache de primeiro nível por padrão, e o escopo do cache é sqlSession. Na mesma SqlSession, execute a mesma consulta sql duas vezes e não faça mais consultas no banco de dados pela segunda vez.

Princípio: O cache de primeiro nível usa armazenamento Hashmap.Quando mybatis executa uma consulta, ele consulta do cache, se não houver consulta do banco de dados no cache. Se o SqlSession executar clearCache () commit ou adicionar operação de modificação de exclusão, limpe o cache.

Existe por padrão, basta entender o resultado da observação

a. Existência de cache (sessão não enviada)

@Test 

public void test01() {
    
     

    SqlSession sqlSession=sqlSessionFactory.openSession();  

    AccountDao accountDao=sqlSession.getMapper(AccountDao.class);  

    Account account=accountDao.queryAccountById(1); 

    System.out.println(account); 

    accountDao.queryAccountById(1);  

} 

O log só imprime um sql

b. Atualize o cache

Os dados em cache são atualizados quando a sessão é enviada

@Test 
public void test02() {
    
     
    SqlSession sqlSession=sqlSessionFactory.openSession();  
    AccountDao accountDao=sqlSession.getMapper(AccountDao.class);  
    Account account=accountDao.queryAccountById(1); 
    System.out.println(account); 
    sqlSession.clearCache(); 
    accountDao.queryAccountById(1);  
} 

efeito:

5. Cache secundário

O cache de primeiro nível está no mesmo sqlSession e o cache de segundo nível está no mesmo namespace, portanto, diferentes sqlsessions com o mesmo namespace podem usar o cache de segundo nível.

cenas a serem usadas

  • Para dados com alta frequência de consulta e baixa frequência de alteração, é recomendável usar o cache secundário.

  • Para solicitações de consulta que são acessadas com frequência e os usuários não têm altos requisitos para resultados de consulta em tempo real, a tecnologia de cache secundário mybatis pode ser usada para reduzir o acesso ao banco de dados e aumentar a velocidade de acesso. Cenários de negócios como: sql de análise estatística demorada, contas de telefone Consulta sql etc.

Configuração de arquivo global (mybatis.xml)

<setting name="cacheEnabled" value="true"/> 
Mapper.xml 中加入 :打开该 mapper 的二级缓存 

<!-- 开启该 mapper 的二级缓存 --> 

<cache/>

Atributos comuns da tag de cache

<cache  

eviction="FIFO" <!--回收策略为先进先出--> 

flushInterval="60000" <!--自动刷新时间 60s--> 

size="512" <!--最多缓存 512 个引用对象--> 

readOnly="true"/> <!--只读--> 

Descrição:

  1. Todas as instruções de seleção no arquivo de instrução de mapeamento serão armazenadas em cache.

  2. Todas as instruções de inserção, atualização e exclusão no arquivo de instrução mapeada irão atualizar o cache.

  3. O cache usará o algoritmo menos usado recentemente (LRU, usado menos recentemente) para recuperar.

  4. O cache será atualizado de acordo com o intervalo de tempo especificado.

  5. O cache irá armazenar 1024 objetos

O objeto PO deve suportar serialização

public class User implements Serializable {
    
     

} 

Desligue o cache de instrução específica no Mapper

Use useCache: o padrão é verdadeiro

<select id="findUserByid" parameterType="int" resultType="User"  

useCache="false"> 

	SELECT * FROM user WHERE id=#{id} 

</select> 

** Atualize o cache secundário **

Ao operar a instrução CUD, o cache de segundo nível é forçado a atualizar, ou seja, o padrão flushCache = "true". Se você deseja desligar a configuração para flushCache = "false", não é recomendado desligar o atualizar, porque a atualização da operação exclui a modificação e é fácil se sujar após fechar os dados.

Teste de cache secundário:

@Test 

public void test03() {
    
     

    SqlSession sqlSession=sqlSessionFactory.openSession();  

    AccountDao accountDao=sqlSession.getMapper(AccountDao.class);  

    Account account=accountDao.queryAccountById(1); 

    System.out.println(account); 

    sqlSession.close(); 

    SqlSession sqlSession2=sqlSessionFactory.openSession(); 

    AccountDao accountDao2=sqlSession2.getMapper(AccountDao.class);  

    accountDao2.queryAccountById(1); 

    sqlSession.close(); 

} 

efeito:

Expandir

Cache distribuído ehcache

Se houver vários servidores, o cache distribuído não será usado e os dados em cache serão armazenados separadamente em cada servidor, o que não é conveniente para o desenvolvimento do sistema. Portanto, um cache distribuído deve ser usado para gerenciar centralmente os dados em cache. Portanto, use o ehcache memcached redis

O Mybatis em si não pode alcançar o cache distribuído, então ele precisa ser integrado com o framework de cache distribuído. EhCache é uma estrutura de cache em processo Java pura, que é rápida e capaz; Ehcache é um cache distribuído Java de código aberto amplamente usado. Principalmente para cache de uso geral, Java EE e contêineres leves. Ele possui recursos como memória e armazenamento em disco, carregador de cache, extensão de cache, manipulador de exceção de cache, filtro de servlet de cache gzip e oferece suporte a REST e API SOAP.

Dependência de Jar

<dependency> 

    <groupId>net.sf.ehcache</groupId> 

    <artifactId>ehcache-core</artifactId> 

    <version>2.4.4</version> 

</dependency> 

<dependency> 

    <groupId>org.mybatis.caches</groupId> 

    <artifactId>mybatis-ehcache</artifactId> 

    <version>1.0.3</version> 

</dependency> 

Configuração de interface de cache

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/> 

Adicione ehcache.xml sob src (não é necessário, nenhuma configuração padrão é usada)

<?xml version="1.0" encoding="UTF-8"?> 

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xsi:noNamespaceSchemaLocation="../bin/ehcache.xsd"> 

<!-- 

name:Cache 的唯一标识 

maxElementsInMemory:内存中最大缓存对象数 

maxElementsOnDisk:磁盘中最大缓存对象数,若是 0 表示无穷大 

eternal:Element 是否永远不过期,如果为 true,则缓存的数据始终有效,如果为 false 

那么还要根据 timeToIdleSeconds,timeToLiveSeconds 判断 

overflowToDisk:配置此属性,当内存中 Element 数量达到 maxElementsInMemory 时, 

Ehcache 将会 Element 写到磁盘中 

timeToIdleSeconds:设置 Element 在失效前的允许闲置时间。仅当 element 不是永久有效 

时使用,可选属性,默认值是 0,也就是可闲置时间无穷大 

timeToLiveSeconds:设置 Element 在失效前允许存活时间。最大时间介于创建时间和失效 

时间之间。仅当 element 不是永久有效时使用,默认是 0.,也就是 element 存活时间无穷 

大 

diskPersistent:是否缓存虚拟机重启期数据 

diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是 120 秒 

diskSpoolBufferSizeMB:这个参数设置 DiskStore(磁盘缓存)的缓存区大小。默认是 

30MB。每个 Cache 都应该有自己的一个缓冲区 

memoryStoreEvictionPolicy:当达到 maxElementsInMemory 限制时,Ehcache 将会根据 

指定的策略去清理内存。默认策略是 LRU(最近最少使用)。你可以设置为 FIFO(先进先 

出)或是 LFU(较少使用) 

--> 

<defaultCache overflowToDisk="true" eternal="false"/> 

<diskStore path="D:/cache" /> 

<!-- 

<cache name="sxtcache" overflowToDisk="true" eternal="false" 

timeToIdleSeconds="300" timeToLiveSeconds="600" maxElementsInMemory="1000" 

maxElementsOnDisk="10" diskPersistent="true"  

diskExpiryThreadIntervalSeconds="300" 

diskSpoolBufferSizeMB="100" memoryStoreEvictionPolicy="LRU" /> 

--> 

teste:

@Test 

public void test04() {
    
     

    SqlSession sqlSession=sqlSessionFactory.openSession();  

    AccountDao accountDao=sqlSession.getMapper(AccountDao.class);  

    Account account=accountDao.queryAccountById(1); 

    System.out.println(account); 

    sqlSession.close(); 

    SqlSession sqlSession2=sqlSessionFactory.openSession(); 

    AccountDao accountDao2=sqlSession2.getMapper(AccountDao.class);  

    accountDao2.queryAccountById(1); 

    sqlSession.close(); 

} 

efeito:

Cache Hit Ratio [com.xxx.dao.AccountDao]:0.5
~~~![在这里插入图片描述](https://img-blog.csdnimg.cn/20201222173926321.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3h5eDEyMzIx,size_16,color_FFFFFF,t_70#pic_center)

Acho que você gosta

Origin blog.csdn.net/xyx12321/article/details/111562914
Recomendado
Clasificación