hibernate search는 hibernate ORM을 사용할 때 RDB 트랜잭션 커밋 시 자동으로 Elasticsearch와 동기화해주는 기능을 한다.
동기화할때 총 네가지 방법으로 할 수 있는데, 이는 sync, write-sync, read-sync, sync 방법이다.
write-sync에 대해서 간단하게 얘기하자면 transaction commit -> es sync 하는 시점에 데이터 동기화를 위해 Elasticsearch가 2xx 응답코드를 줄 때까지 애플리케이션을 block 시킨다.
sync하는 과정에서 클라이언트나
Elasticsearch 백엔드 발생하여 동기화가 안 될 수 있는데 hibernate search의 failureHandler 인터페이스를 구현해서 대응할 수 있다 (알림을 보내거나 재시도를 하거나)
문제는 얼마 전에 RDB와 Elasticsearch간에 데이터 동기화가 되지 않았는데 failureHandler가 발동하지 않고 Elasticsearch에도 아무런 로그를 남기지 않았다는 것이다.
좀 더 자세히 들여다보니 같이 색인 된 여러 문서 중 한 문서만 동기화되지 않았다. 그 이유는 Elasticsearch bulk API(\_shards.failed 및 error 필드)를 찾아보면서 알 수 있었는데, Elasticsearch는 같은 요청에 여러 문서를 동시에 색인했어도 샤드 실패 유무에 따라 어떤 문서는 색인이 되고 어떤 문서는 색인이 안 됐을 수 있다.
일반적으로 우리는 RDB 트랜잭션처럼 하나가 실패하면 요청 자체가 실패할 것이라고 생각했을 텐데 Elasticsearch의 트랜잭션은 요청 레벨이 아니라 샤드 레벨에서 트랜잭션을 관리하고 있는 것이다. 해결방법은 Elasticsearch 클라이언트가 남기는 로그를 로깅해서 \_shards.failed 카운트가 올라가있으면 조치를 취하는 것이다. 애플리케이션 코드에서 응답을 받을 수 있는 구조로 설계되지 않아서 로그를 확인해야하는 번거로움이 있다.