2012-04-24 3 views
1

CMT를 사용하는 Java EE 서버에서 ehcache를 사용하여 EJB (Business Object Layer)와 JDBC (JDBC를 사용하는 POJO) 사이에 캐싱 계층을 구현하고 있습니다. 나는 자기 기입 식 Ehcache를 사용하면서 동일한 레코드에 액세스하는 두 스레드 사이의 경쟁 조건을 경험 한 것 같다. 캐시는 레코드의 기본 키에서 키가 지정됩니다.Ehcache가 데이터베이스와 동기화되지 않습니다.

  1. 첫 번째 스레드가 데이터베이스에 기록을 갱신하고 캐시에서 레코드를 제거합니다 (그러나 데이터베이스는 반드시 즉시 발생하지 않습니다 커밋 - 따라야 할 다른 쿼리가있을 수 있습니다.) :

    시나리오는

  2. 두 번째 스레드가 레코드를 읽음으로써 캐시가 다시 채워집니다.
  3. 첫 번째 스레드가 트랜잭션을 커밋합니다.

이 모든 것이 1 초도 안되는 순간입니다. 이로 인해 캐시가 데이터베이스와 동기화되지 않고 다른 업데이트가 수행되거나 캐시에서 항목이 만료 될 때까지 부실 캐시 데이터를 반환하는 레코드를 연속해서 읽습니다. 짧은 기간 (트랜잭션의 일반적인 길이) 동안 오래된 데이터를 처리 할 수는 있지만 오브젝트를 캐시하려는 시간 (분)은 처리 할 수 ​​없습니다.

이 경쟁 조건을 피하기위한 제안 사항이 있으십니까?

UPDATE : 트랜잭션이 확실히 이상적 일 것이다 최선을 다하고 후 캐시를 지우

. 문제는 CMT를 사용하는 J2EE 환경에서 비즈니스 계층 (stateless session EJB)과 데이터 액세스 계층 사이에 캐싱 계층을 끼워 넣을 때 어떻게해야할까요?

이 제약 조건에 대해 명확히 알기 위해 문제의 메서드 호출은 전후에 발생하는 추가 메서드 호출과 같은 트랜잭션 일 수도 있고 아닐 수도 있습니다. 클라이언트 코드에서 예상하는 트랜잭션 경계를 변경하므로 커밋을 강제로 수행 할 수 없습니다 (또는 별도의 트랜잭션에서이 작업을 수행 할 수 없음). 후속 예외는 전체 트랜잭션을 롤백하지 않습니다 (이 경우 캐시를 unneseccarily 지우면 허용되는 부작용입니다). 본질적으로 클라이언트가 사용할 수있는 진입 점을 트랜잭션으로 제어 할 수 없습니다. 클라이언트 응용 프로그램에 캐시 지우기의 호의성을 강제하는 것은 합리적이지 않습니다.

전체 트랜잭션이 EJB 컨테이너에 의해 커밋 될 때까지 캐시 지우기 작업을 연기 할 수 있기를 원하지만 그 로직에 연결하여 상태 비 저장 세션 빈으로 내 자신의 코드를 실행할 방법이 없습니다.

업데이트 # 2 : http://ehcache.org/documentation/apis/jta

이 2으로 Ehcache로 업그레이드를 의미 지금까지

가장 유망한 솔루션의 주요 설계 변경의 짧은으로 Ehcache 2.0의 JTA 지원을 사용하는 것입니다. x와 데이터베이스에 대한 XA 트랜잭션을 가능하게하여 부정적인 부작용을 일으킬 수 있습니다. 그러나 그것은 "옳은"방법처럼 보인다.

답변

0

트랜잭션을 사용 중입니다.commit 이후에 캐시 을 제거하는 것이 더 중요합니다. 변경이 실제로 발생하는 경우입니다.

그런 식으로 트랜잭션의 기간 동안에 만 이전 데이터를 볼 수 있으며 나중에 모든 읽기가 최신보기를 갖습니다.

업데이트 : 이것은 CMT에만 해당되므로 SessionSynchronization 인터페이스를 살펴보고 afterCompletion() 메서드를 사용해야합니다. 이것은 this tutorial.에 표시됩니다.

+0

물론 이것은 이상적이지만, 어떻게해야합니까? 제약 조건을 명확히하기 위해 질문을 업데이트했습니다. –

+0

@Chris 답변을 업데이트했습니다. 도움이되기를 바랍니다. – jmruc

+0

안녕하세요. Kril, SessionSynchronization 인터페이스는 Stateful Session Beans에만 사용할 수 있습니다. 무국적으로 사용할 수있는 경우 확실히 훌륭한 솔루션이 될 것입니다. –

관련 문제