[java] 최대 절전 모드 2 단계 캐시를 언제 어떻게 사용합니까?

최대 절전 모드가 두 번째 수준 캐시에 도달하고 캐시가 무효화되는시기를 이해하는 데 어려움이 있습니다.

이것이 내가 현재 이해하고있는 것입니다.

  • 두 번째 레벨 캐시는 세션 사이에 엔티티를 저장하고 범위는 SessionFactory입니다.
  • 캐시 할 엔티티를 지정해야합니다. 엔티티는 기본적으로 캐시되지 않습니다.
  • 쿼리 캐시는 쿼리 결과를 캐시에 저장합니다.

내가 이해하지 못하는 것은

  • 최대 절전 모드는 언제이 캐시에 도달합니까?
  • 두 번째 수준 캐시를 설정했지만 쿼리 캐시는 설정하지 않았다고 가정 해 보겠습니다. 내 고객을 캐시하고 싶습니다. 50000 명이 있습니다. 어떤 방법으로 캐시에서 고객을 검색 할 수 있습니까?
  • 캐시에서 ID로 가져올 수 있다고 가정합니다. 쉽지만 캐싱 할 가치가 없습니다. 하지만 모든 고객과 함께 계산을하고 싶다면 어떨까요? 고객 목록을 표시하고 싶은데 어떻게 액세스 할 수 있습니까?
  • 쿼리 캐싱이 비활성화 된 경우 모든 고객을 어떻게 확보 할 수 있습니까?
  • 누군가 고객 중 하나를 업데이트하면 어떻게됩니까?
    • 해당 고객이 캐시에서 무효화됩니까, 아니면 모든 고객이 무효화됩니까?

아니면 캐싱이 완전히 잘못되었다고 생각합니까? 이 경우 두 번째 수준 캐시를 더 적절하게 사용하는 것은 무엇입니까? 최대 절전 모드 문서는 캐시가 실제로 어떻게 작동하는지 전혀 명확하지 않습니다. 설정 방법에 대한 지침 만 있습니다.

업데이트 :
그래서 두 번째 수준 캐시 (쿼리 캐시 없음)가 ID로 데이터를로드하는 데 유용 할 것임을 이해하게되었습니다. 예를 들어 웹 응용 프로그램의 모든 요청에서 권한을 확인하려는 사용자 개체가 있습니다. 사용자를 두 번째 수준 캐시에 캐시하여 데이터베이스 액세스를 줄이는 것이 좋은 경우입니까? 세션에 사용자 ID를 저장하거나 권한을 확인해야 할 때마다 ID로 사용자를로드하고 권한을 확인합니다.



답변

우선, 프로세스 레벨 캐시 (또는 Hibernate에서 호출하는 2 차 레벨 캐시)에 대해 이야기합시다. 작동하려면

  1. 캐시 공급자 구성
  2. 캐시 할 엔티티를 최대 절전 모드에 알려줍니다 (이러한 종류의 매핑을 사용하는 경우 hbm.xml 파일에서 바로).

캐시 공급자에게 저장해야하는 개체 수와 무효화해야하는시기 / 이유를 알려줍니다. 따라서 Book과 Author 엔티티가 있다고 가정 해 봅시다. DB에서 가져올 때마다 캐시에없는 엔티티 만 실제로 DB에서 선택됩니다. 이렇게하면 성능이 크게 향상됩니다. 다음과 같은 경우에 유용합니다.

  • Hibernate를 통해서만 데이터베이스에 씁니다 (캐시의 엔티티를 언제 변경하거나 무효화해야하는지 알 수있는 방법이 필요하기 때문)
  • 자주 물건을 읽는다
  • 단일 노드가 있고 복제가 없습니다. 그렇지 않으면 캐시 자체를 복제해야합니다 (JGroups와 같은 분산 캐시 사용). 더 많은 복잡성이 추가되고 비공유 앱만큼 확장되지 않습니다.

그렇다면 캐시는 언제 작동합니까?

  • 사용자 session.get()또는 session.load()이전에 선택되어 캐시에있는 개체 캐시는 ID가 키이고 속성이 값인 저장소입니다. 따라서 ID로 검색 할 수있는 경우에만 DB 히트를 없앨 수 있습니다.
  • 연결이 지연로드되는 경우 (또는 조인 대신 선택 항목으로 즉시로드되는 경우)

그러나 다음과 같은 경우에는 작동하지 않습니다.

  • ID로 선택하지 않는 경우. 다시-두 번째 수준 캐시는 엔티티의 ID 맵을 다른 속성에 저장하므로 (실제로 객체를 저장하지 않고 데이터 자체를 저장함) 조회가 다음과 같으면 from Authors where name = :name캐시를 누르지 않습니다.
  • HQL을 사용하는 경우 (를 사용하더라도 where id = ?).
  • 매핑에서을 설정하면 fetch="join"연결을로드 할 때 별도의 select 문 대신 모든 곳에서 조인이 사용됩니다. 프로세스 수준 캐시는가 fetch="select"사용되는 경우에만 자식 개체에서 작동합니다 .
  • fetch="select"HQL에서 조인을 사용하여 연결을 선택 하더라도 해당 조인은 즉시 발급되고 hbm.xml 또는 주석에 지정된 내용을 덮어 씁니다.

이제 쿼리 캐시에 대해. 별도의 캐시가 아니라 프로세스 수준 캐시에 추가 된 것입니다. 국가 엔티티가 있다고 가정 해 보겠습니다. 정적이므로라고 말할 때마다 동일한 결과 집합이 있음을 알고 from Country있습니다. 이것은 쿼리 캐시에 대한 완벽한 후보이며, 자체적 으로 ID 목록을 저장하고 다음에 모든 국가를 선택할 때이 목록을 프로세스 수준 캐시로 반환하고 후자는 각 ID에 대한 개체를 반환합니다. 이러한 개체는 이미 2 단계 캐시에 저장되어 있습니다. 항목과 관련된 항목이 변경 될 때마다 쿼리 캐시가 무효화됩니다. 따라서 from Authors쿼리 캐시에 배치되도록 구성했다고 가정 해 보겠습니다 . 작성자가 자주 변경되므로 효과적이지 않습니다.


답변

  • 두 번째 수준 캐시는 키-값 저장소입니다. ID로 엔티티를 가져 오는 경우에만 작동합니다.
  • 두 번째 레벨 캐시는 엔티티가 최대 절전 모드를 통해 업데이트 / 삭제 될 때 엔티티별로 무효화 / 업데이트됩니다. 데이터베이스가 다른 방식으로 업데이트 된 경우 무효화되지 않습니다.
  • 쿼리 (예 : 고객 목록)의 경우 쿼리 캐시를 사용합니다.

실제로는 키-값 분산 캐시를 사용하는 것이 유용합니다. 이것이 memcached이고 페이스 북, 트위터 등을 지원합니다. 그러나 id로 조회하지 않으면 그다지 유용하지 않습니다.


답변

파티에 늦었지만 많은 개발자들이 묻는 질문에 체계적으로 대답하고 싶었습니다.

여기에 귀하의 질문을 하나씩 받아들이는 것이 내 대답입니다.

Q. 최대 절전 모드는 언제이 캐시에 도달합니까?

A. 첫 번째 수준 캐시세션 개체 와 연결되어 있습니다. 두 번째 수준 캐시세션 팩토리 개체 와 연결됩니다 . 첫 번째에서 개체가 발견되지 않으면 두 번째 수준이 확인됩니다.

Q. 두 번째 수준 캐시를 설정했지만 쿼리 캐시는 설정하지 않았다고 가정 해 보겠습니다. 내 고객을 캐시하고 싶습니다. 50000 명이 있습니다. 어떤 방법으로 캐시에서 고객을 검색 할 수 있습니까?

A. 업데이트에서 답변을 받았습니다. 또한 쿼리 캐시는 개체의 ID 목록 만 저장하고 해당 개체의 ID는 동일한 두 번째 수준 캐시에 저장됩니다. 따라서 쿼리 캐시를 활성화하면 동일한 리소스를 활용하게됩니다. 깔끔하지?

Q. 캐시에서 ID로 가져올 수 있다고 가정합니다. 쉽지만 캐싱 할 가치가 없습니다. 하지만 모든 고객과 함께 계산을하고 싶다면 어떨까요? 고객 목록을 표시하고 싶은데 어떻게 액세스 할 수 있습니까?

A. 위에 답변했습니다.

Q. 쿼리 캐싱이 비활성화 된 경우 모든 고객을 어떻게 확보 할 수 있습니까?

A. 위에 답변했습니다.

Q. 누군가 고객 중 하나를 업데이트하면 어떻게됩니까? 해당 고객이 캐시에서 무효화됩니까, 아니면 모든 고객이 무효화됩니까?

A. Hibernate는 전혀 알지 못하지만 다른 타사 IMDG / 분산 캐시를 사용하여 최대 절전 모드 2 단계 캐시 로 구현하고 이를 무효화 할 수 있습니다. 예를 들어 TayzGrid 는 그러한 제품 중 하나이며 더 많은 것들이 있습니다.


답변

Hibernate 2 단계 캐시는 이해하고 구현하기가 약간 까다 롭습니다. 귀하의 질문에 따라 말할 수있는 내용은 다음과 같습니다.

Hibernate는 언제이 캐시를 적중합니까?

제안한대로 Hibernate L2 캐시 (활성화 된 경우, 기본적으로 켜져 있지 않음)는 L1 캐시 후에 만 ​​쿼리됩니다. 여러 세션에서 데이터가 보존되는 키-값 캐시입니다.

두 번째 수준 캐시를 설정했지만 쿼리 캐시는 설정하지 않았다고 가정 해 보겠습니다. 내 고객을 캐시하고 싶습니다. 50000 명이 있습니다. 어떤 방법으로 캐시에서 고객을 검색 할 수 있습니까?

고객 데이터가 정적이고 관계형 데이터베이스에서 검색되기 때문에 쿼리 캐싱이이 사용 사례에 가장 적합합니다.

누군가 고객 중 하나를 업데이트하면 어떻게됩니까? 해당 고객이 캐시에서 무효화됩니까, 아니면 모든 고객이 무효화됩니까?

사용중인 특정 Hibernate 캐시 전략에 따라 다릅니다. Hibernate에는 실제로 네 가지 캐시 전략이 있습니다.

READ_ONLY : 개체는 캐시 내에서 한 번 변경되지 않습니다.

NONSTRICT_READ_WRITE : 해당 데이터베이스 항목이 업데이트 된 후 (최종적으로) 개체가 변경됩니다. 이것은 궁극적 인 일관성을 보장합니다.

READ_WRITE : 해당 데이터베이스 항목이 업데이트 된 후 객체가 (즉시) 변경됩니다. 이것은 “소프트”잠금을 사용하여 강력한 일관성을 보장합니다.

TRANSACTIONAL는 : 데이터 무결성을 보장 분산 XA 트랜잭션을 사용하여 변화를 개체; 이것은 완전한 성공을 보장하거나 모든 변경 사항을 롤백합니다. 그러나 이러한 네 가지 경우 모두에서 단일 데이터베이스 항목을 업데이트해도 캐시의 전체 고객 목록이 무효화되지는 않습니다. Hibernate는 그것보다 조금 더 똑똑합니다 🙂

Hibernate에서 L2 캐싱이 작동하는 방법에 대해 자세히 알아 보려면 “Hibernate L2 캐시 란 무엇입니까?”기사 또는 Redis를 사용한 Hibernate의 캐싱 심층 기사를 참조하십시오.


답변