Mybatis의 기본 및 보조 캐시의 원칙 및 사용, 보조 캐시 및 캐시 새로 고침의 지정된 방법 금지, Ehcache의 Mybatis 통합, 보조 캐시의 사용 시나리오 및 제한 사항 -day03

첫 번째 섹션 Mybatis 캐시

1.1 Mybatis 캐시 이해

  • Mybatis의 캐시는 첫 번째 수준 캐시와 두 번째 수준 캐시를 포함하여 최대 절전 모드의 캐시와 유사 합니다 . 첫 번째 수준 캐시는 기본적으로 사용되며 두 번째 수준 캐시는 수동으로 켜야합니다.
  • 1 단계 캐시는 sqlsession을 의미하며 sqlsession에는 맵 구조 인 데이터 영역이 있으며,이 영역은 1 단계 캐시 영역입니다. 첫 번째 레벨 캐시의 키는 SQL 문, 조건 및 명령문과 같은 정보로 구성된 고유 한 값입니다. 첫 번째 수준 캐시의 값은 쿼리의 결과 개체입니다.
  • 2 단계 캐시는 동일한 네임 스페이스 아래의 매퍼를 의미하며 2 단계 캐시에는 맵 구조도 있으며이 영역은 1 단계 캐시 영역입니다.
    여기에 사진 설명 삽입

sqlSession1에서 데이터 일부를 가져 오면 SQL을 사용하지 않고 sqlSession2에서 동일한 데이터를 가져올 수 있으며 이때 보조 캐시를 사용해야합니다.
보조 캐시는 모든 sqlSessions에서 공유됩니다.

1.2 레벨 1 캐시

원리

  • 첫 번째 질의의 경우 id가 1 인 사용자가 sql을 실행하고 기본적으로 1 차 캐시가 수행되며 1 차 캐시 맵에 데이터가 저장되며, 사용자 수정, 추가, 삭제가 제출되면 1 차 캐시는 지워진다. , ID가 1 인 사용자를 다시 쿼리하고 sql을 다시 실행해야합니다.
    여기에 사진 설명 삽입

사용 및 테스트

  • 이전 save 및 findUserById 메소드
    여기에 사진 설명 삽입
    여기에 사진 설명 삽입
  • 직렬화 인터페이스 (즉, 직렬화 가능 플래그)를 구현하도록 구성 할 클래스를 확인하십시오. 그렇지 않으면 오류가보고됩니다.
    여기에 사진 설명 삽입

여기에 사진 설명 삽입

	@Test
    public void test1() throws IOException {
    
    
        //1.读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.通过SqlSessionFactory创建SqlSession
        SqlSession sqlSession = sessionFactory.openSession();

        //默认情况下的一级缓存是开启的
        //4.通过会话获取dao接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        User user1 = userMapper.findUserById(1);
        System.out.println(user1);

        //第二次不会执行sql
        User user2 = userMapper.findUserById(1);
        System.out.println(user2);

        sqlSession.close();
    }
  • 저장, 업데이트, 삭제 등이 포함되면 첫 번째 수준 캐시가 자동으로 지워집니다.
    여기에 사진 설명 삽입
	@Test
    public void test2() throws IOException {
    
    
        //1.读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.通过SqlSessionFactory创建SqlSession
        SqlSession sqlSession = sessionFactory.openSession();

        //默认情况下的一级缓存是开启的
        //保存、删除、更新后,一级缓存会自动清空,下次查询会再次执行sql
        //4.通过会话获取dao接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        User user1 = userMapper.findUserById(1);
        System.out.println(user1);

        //保存一个新用户
        userMapper.save(new User("shu1","男",new Date(),"北京市"));
        //若要保存到数据库记得提交事务,否则不影响数据库,这里只做演示一级缓存可不提交
        sqlSession.commit();
        //此时第二次会执行sql
        User user2 = userMapper.findUserById(1);
        System.out.println(user2);

        sqlSession.close();
    }

여기에 사진 설명 삽입

1.3 보조 캐시

원리

여기에 사진 설명 삽입

사용 및 테스트

  1. 보조 캐시의 일반 스위치를 켭니다 (글로벌 구성 파일에 구성됨) (더 많은 설정은 day01에 설정 됨).
    여기에 사진 설명 삽입
  2. UserMapper.xml에서 보조 캐시 구성
    여기에 사진 설명 삽입
  3. 테스트
  • 직렬화 인터페이스 (즉, 직렬화 가능 플래그)를 구현하도록 구성 할 클래스를 확인하십시오. 그렇지 않으면 오류가보고됩니다.
    여기에 사진 설명 삽입
    여기에 사진 설명 삽입
	//二级缓存
    @Test
    public void test3() throws IOException {
    
    
        //1.读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.通过SqlSessionFactory创建SqlSession
        SqlSession sqlSession1 = sessionFactory.openSession();
        SqlSession sqlSession2 = sessionFactory.openSession();

        //默认情况下的一级缓存是开启的
        //保存、删除、更新后,一级缓存会自动清空,下次查询会再次执行sql
        //4.通过会话获取dao接口
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);


        User user1 = userMapper1.findUserById(1);
        System.out.println(user1);
        //session关闭了,数据才会写入二级缓存
        sqlSession1.close();

        User user2 = userMapper2.findUserById(1);
        System.out.println(user2);
        sqlSession2.close();
    }
  1. 삽입, 업데이트, 삭제 등의 작업을 수행하면 보조 캐시가 지워집니다.
	@Test
    public void test4() throws IOException {
    
    
        //1.读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.通过SqlSessionFactory创建SqlSession
        SqlSession sqlSession1 = sessionFactory.openSession();
        SqlSession sqlSession2 = sessionFactory.openSession();
        SqlSession sqlSession3 = sessionFactory.openSession();

        //默认情况下的一级缓存是开启的
        //保存、删除、更新后,一级缓存会自动清空,下次查询会再次执行sql
        //4.通过会话获取dao接口
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);

        User user1 = userMapper1.findUserById(1);
        System.out.println(user1);
        sqlSession1.close();

        //保存用户,二级缓存也会清空
        userMapper3.save(new User("shu2","男",new Date(),"上海市"));
        sqlSession3.commit();
        sqlSession3.close();

        User user2 = userMapper2.findUserById(1);
        System.out.println(user2);
        sqlSession2.close();

    }

여기에 사진 설명 삽입
여기에 사진 설명 삽입

지정된 메서드의 두 번째 수준 캐시 비활성화

여기에 사진 설명 삽입

  • 지정된 메서드의 두 번째 수준 캐시가 비활성화되고이 메서드의 두 번째 수준 캐시가 적용되지 않으며 다른 메서드는 영향을주지 않습니다.
    여기에 사진 설명 삽입

캐시 새로 고침

  • 지정된 메서드의 두 번째 수준 캐시가 위에서 비활성화되어 있습니다.이 메서드는 두 번째 수준 캐시를 반영하는 데 사용됩니다. 비활성화를 제거해야합니다. 그렇지 않으면 캐시가 새로 고쳐지지 않습니다.
    여기에 사진 설명 삽입
    여기에 사진 설명 삽입

요약하자면

첫 번째 수준 캐시와 두 번째 수준 캐시의 공통점 : 삽입, 업데이트 및 삭제와 같은 작업을 수행하면 캐시가 지워집니다.

1.4 ehcache 통합

  • 질문 : Mybatis와 함께 제공되는 캐시를 사용하지 않고 ehcache 캐시를 통합하는 이유는 무엇입니까?
  • 답변 : Mybatis 자체는 지속성 계층 프레임 워크이며 전용 캐싱 프레임 워크가 아니므로 캐싱 구현은 분산을 지원하기에 충분하지 않지만 Ehcache는 분산 캐싱 프레임 워크입니다.

배포되는 항목

  • 성능 향상을 위해 시스템은 일반적으로 분산 배포 (클러스터 배포)를 채택합니다.
    여기에 사진 설명 삽입

통합 사고

  • 캐시에는 표준화 된 인터페이스 캐시 (사용하고 싶은 사람, 구현하고 해당 메서드 작성)가 있으며 기본 구현은 mybatis의 PerpetualCache입니다. mybatis의 보조 캐시를 통합하려면 캐시 인터페이스를 구현하십시오.
    여기에 사진 설명 삽입
  • Mybatis는 구현 캐시와 함께 제공됩니다.
    여기에 사진 설명 삽입

통합 단계

1 단계 : jar 패키지 가져 오기

여기에 사진 설명 삽입
여기에 사진 설명 삽입

  • ehcache에서 구현 한 캐시를 볼 수 있습니다.
    여기에 사진 설명 삽입

2 단계 : 매핑 파일에서 캐시 태그 구성

여기에 사진 설명 삽입

	<!--配置缓存
    type不写,默认使用的就是mybatis自带的缓存技术,perpetualCache永久缓存
    -->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

3 단계 : src 아래에 ehcache 구성 파일 추가

여기에 사진 설명 삽입

  • src 디렉토리에 복사하고 ehcache.xml로 이름을 바꿉니다 (주석 삭제 후).
    여기에 사진 설명 삽입

  • maxElementsInMemory : 메모리 기반 캐시에 저장할 수있는 최대 개체 수를 설정합니다.

  • eternal : 개체가 영구적인지 여부를 설정합니다. true는 만료되지 않음을 의미하고, false이면 timeToIdleSeconds 및 timeToLiveSeconds에 따라 판단해야합니다.

  • timeToIdleSeconds : 개체가 유휴 상태가되는 최대 시간 (초)을 설정합니다.이 시간이 지나면 개체가 만료됩니다. 객체가 만료되면 EHCache는 캐시에서 객체를 제거합니다. 이 값이 0이면 개체가 무기한 유휴 상태 일 수 있음을 의미합니다. (단위는 초)

  • timeToLiveSeconds : 개체가 유지되는 가장 긴 시간을 설정합니다.이 시간이 지나면 개체가 만료됩니다. 이 값이 0이면 개체가 캐시에 무기한 존재할 수 있음을 의미합니다. 속성 값은 timeToIdleSeconds 속성 값 (초) 보다 크거나 같아야합니다.

  • overflowToDisk : 내부 캐시의 개체 수가 상한에 도달 한 후 오버플로 개체를 하드 디스크 기반 캐시에 쓸지 여부를 설정합니다.

  • diskPersistent : jvm이 종료 될 때 객체 (하드 디스크에 저장 됨)를 유지할지 여부, true 또는 false는 선택 사항이며 기본값은 false입니다.

  • diskExpiryThreadIntervalSeconds : 만료 된 개체 지우기 전용 수신 스레드의 폴링 시간을 지정합니다. (단위는 초)

  • memoryStoreEvictionPolicy : 메모리 캐시가 최대 값에 도달하고 새 요소가 추가되면 캐시의 요소가 디스크에서 제거 될 때의 정책입니다. 기본값은 LRU (최근에 가장 적게 사용됨), 옵션은 LFU (가장 적게 사용됨, 가장 적게 사용됨) 및 FIFO (선입 선출)입니다.

  • LRU (최근에 가장 적게 사용 된 항목) : 캐시 된 요소에 타임 스탬프가 있습니다. 캐시 용량이 가득 차서 새 요소를 캐시 할 공간을 확보해야하는 경우 타임 스탬프가 현재 시간에서 가장 먼 기존 캐시 요소의 요소 캐시에서 지워집니다.

  • LFU (덜 자주 사용됨) : 캐시 된 요소에 적중 속성이 있으며 적중 값이 가장 작은 요소가 캐시에서 지워집니다.

4 단계 : 테스트

  • 이전 테스트 보조 캐시 사용
	//二级缓存
    @Test
    public void test3() throws IOException {
    
    
        //1.读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.通过SqlSessionFactory创建SqlSession
        SqlSession sqlSession1 = sessionFactory.openSession();
        SqlSession sqlSession2 = sessionFactory.openSession();

        //默认情况下的一级缓存是开启的
        //保存、删除、更新后,一级缓存会自动清空,下次查询会再次执行sql
        //4.通过会话获取dao接口
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

        User user1 = userMapper1.findUserById(1);
        System.out.println(user1);
        //session关闭了,数据才会写入二级缓存
        sqlSession1.close();

        User user2 = userMapper2.findUserById(1);
        System.out.println(user2);
        sqlSession2.close();
    }
  • SQL을 한 번 실행하고 두 번째로 두 번째 수준 캐시에서 가져옵니다.
    여기에 사진 설명 삽입

1.5 보조 캐시의 사용 시나리오

  • 높은 액세스 응답 속도가 필요하지만 실시간 성능이 낮은 쿼리의 경우 보조 캐시 기술을 사용할 수 있습니다 .
    참고 : 2 단계 캐시를 사용하는 경우 2 단계 캐시를 정기적으로 새로 고치려면 새로 고침 간격 (캐시 태그에 flashInterval 속성이 있음)을 설정해야합니다.이 새로 고침 간격은 30 분, 60 분 등과 같은 특정 요구 사항에 따라 설정됩니다. 밀리 초입니다.
  • 예 : 캐시 새로 고침 간격을 60 분으로 설정 (60 분마다 캐시 지우기)
    여기에 사진 설명 삽입

1.6 두 번째 레벨 캐시의 한계

  • Mybatis 2 단계 캐시는 세분화 된 데이터에 대해 제대로 구현되지 않았습니다.

  • 예 : 제품 정보 캐시. 제품 정보 조회 방문량이 많기 때문에 사용자는 매번 최신 제품 정보를 조회해야합니다. 이때 2 차 캐시를 사용하는 경우 제품 변경시 캐시 된 제품 정보 만 새로 고칠 수 없습니다. 2 차 캐시가 매퍼 수준이기 때문에 다른 제품 캐시 정보를 새로 고치지 않으며, 제품 정보가 업데이트되면 모든 제품의 정보 캐시 데이터가 지워집니다.

  • 이러한 문제를 해결하려면 데이터를 필요에 따라 비즈니스 계층에서 대상 방식으로 캐시해야합니다.

  • 예를 들어 자주 변경되는 데이터에 대한 작업을 다른 네임 스페이스의 매퍼에 별도로 배치 할 수 있습니다.

추천

출처blog.csdn.net/qq_43414199/article/details/108883820