2 minute read

1차 캐시는 알겠는데 2차캐시는 뭐야??

1. 1차 캐시 (트랜젝션 단위 캐시)

네트 워크를 통해 데이터베이스에 접근하는 시간 비용은 애플리케이션 서버에서 내부 메모리에 접근하는 시간 비용보다 훨씬 비싸다, 따라서 조회한 데이터를 메모리에서 캐시해서 데이터베이스에 접근 횟수를 줄일수 있다면 애플리케이션의 성능을 획기적으로 개선할수 있다.

  • 일반적인 웹 애플리케이션 환경은 트랜잭션이 시작하고 종료할 떄까지만 1차캐시가 유효하다.
  • OSIV를 사용해도 클라이언트의 요청이 들어올 때부터 끝날때 까지만 1차캐시가 유효하다.

영속성 컨텍스트(entityManager) 내부에서 엔티티를 보관하는 저장소를 1차 캐시라 한다.

  • 1차 캐시는 영속성 컨텍스트 내부에 있다. 엔티티 매니저로 조회하거나, 변경하는 모든 엔티티는 1차 캐시에 저장이 된다.
  • 1차 캐시는 끄고, 킬수 있는 기능이 아닌, 영속성 컨텍스트 자체가 사실상 1차 캐시라 할 수 있다.

1차 캐시의 동작 방식

  • 최초 조회할 떄는 1차 캐시에 엔티티가 없기 떄문에 데이터 베이스에서 엔티티를 조회한다.
  • 엔티티를 1차 캐시에 보관한다.
  • 1차 캐시에 보관된 겨로가를 반환한다.
  • 이후 같은 엔티티를 조회하면 1차 캐시에 같은 엔티티가 있으므로 데이터 베이스를 조회하지 않고 1차 캐시의 엔티티를 그대로 반환한다.
  • 1차 캐시는 객체의 동일성 == 을 보장 한다.

2. 2차 캐시란? (애플리케이션 범위의 캐시)

애플리케이션에서 공유하는 캐시를 JPA는 공유 캐시(Shared Cache)라 하는데 일반적으로 2차 캐시 (Second Level Cache, L2 Cache)라 부른다. __2차 캐시는 애플리케이션 범위의 캐시__이다. 따라서 애플리케이션을 종료할 떄까지 캐시가 유지된다. 분산 캐시나 클러스터링 환경의 캐시는 애플리케이션 보다 더 오래 유지 될 수 있다.

엔티티 매니저를 통해 데이터를 조회할 떄 우선 2차 캐시에서 찾고 없으면 데이터베이스에서 찾는다. 2차 캐시를 적절히 활용하면 데이터 베이스 조회 횟수를 줄일수 있다.

2차 캐시의 동작 방식

  • 영속성 컨텍스트는 엔티티가 필요하면 2차 캐시를 조회한다.
  • 2차 캐시에 엔티티가 없으면 데이터베이스를 조회한다.
  • 결과를 2차 캐시에 보관한다.
  • 2차 캐시는 자신이 보관하고 있는 엔티티를 복사해서 반환한다.
  • 2차 캐시에 저장되어 있는 엔티티를 조회하면 복사본을 만들어 반환한다.
  • 2차 캐시는 데이터베이스 기본 키를 기준으로 캐시하지만 영속성 컨텍스트가 다르면 객체의 동일성을 보장하지 안흔다

2차 캐시와 1차 캐시의 차이

2차 캐시는 동시성을 극대화 하기 위해 캐시 한 객체를 직접 반환하지 않고 복사본을 만들어 반환한다. 여기서 복사본을 반환하는 이유는 캐시한 객체를 그대로 반환하면 여러 곳에서 같은 객체를 동시에 수정하는 문제가 발생할수 있기 떄문이다.

동시성은 싱클 코엉서 멀티 스레드를 동작시키기 위한 방식으로 멀티 태스킹을 위해 여래 개의 스레드가 번갈아 가면서 실행되는 성질을 말한다. 동시성을 이용한 싱글 코어의 멀티 태스킹은 각 스레드들이 병렬적으로 실행되는 것처럼 보이지만 사실은 번갈아 가면 조금씩 실행되고 있는것이다.

그렇다고 이것을 해결하기 위해 객체에 락을 걸어두면 성능 및 동시성이 떨어질수 있다. 그래서 2차 캐시는 원본 대신 복사본을 반환한다. 2차 캐시를 잘만 사용하면 1차 캐시의 동시성 문제를 해결하고 애플리케이션의 조회 성능을 끌어 올릴수 있따.

2차 캐시 사용방법

캐시 모드를 설정하려면 Entity 객체 위해 @Cacheable을 작성한다. 그리고 application.yml 에 아래 설정을 부여한다 .

spring.jpa.properties.hibernate.cache.use_second_level_cache = true
// 2차 캐시 활성화합니다.

spring.jpa.properties.hibernate.cache.region.factory_class
// 2차 캐시를 처리할 클래스를 지정합니다.

spring.jpa.properties.hibernate.generate_statistics = true
// 하이버네이트가 여러 통계정보를 출력하게 해주는데 캐시 적용 여부를 확인할 수 있습니다.
@Entity  // 2차캐시 활성화. true는 기본 값이라 생략가능 @Cacheable(value=true)
@Cacheable
public class Team {
	@Id @GeneratedValue
	private Long id;
	...
}

@Cacheable을 붙이지 않고 사용하는 방법

spring.jpa.properties.javax.persistence.sharedCache.mode= (기본값) Enable_selective

cache mode 5가지

  1. ALL : 모든 엔티티를 캐시한다.
  2. NONE : 캐시를 사용하지 않는다.
  3. ENABLE_SELECTIVE : Cacheable(true)로 설정된 엔티티만 캐시를 적용한다.
  4. DISABLE_SELECTIVE : 모든 엔티티를 캐시하는데 Cacheable(false)만 캐시하지 안흔다.
  5. UNSPECIFIED : JPA 구현체가 정의한 설정에 따른다

@Cacheable 속성 전략

  • usage : CacheConcurrencyStrategy를 사용해서 캐시 동시성 전략을 설정한다.
  • region: 캐시 지역을 설정한다.
  • include : 연관 객체를 캐시에 포함할지 선택한다. all, non-lazy 등을 선택 가능하다.

캐시 동시성 전략

  • READ_ONLY : 자주 조회하고 수정 작업을 하지 않는 데이터에 적합하다.
  • READ_WRITE : 조회 및 수정 작업을 하는 데이터에 적합, Phantom Read가 발생할 수 있으므로 SERIALIZABLE 격리 수준에서는 사용불가
  • NONSTRICT_READ_WRITE : 거의 수정 작업을 하지 않는 데이터에 적합

출처: https://junghyungil.tistory.com/203 [인생을 코딩하다.:티스토리]

Categories:

Updated:

Comments