상품 검색 시 동일한 상품 데이터에 대해 동일한 검색어로 여러번 검색 시 결과 정렬이 근소하게 바뀌는 현상이 발생했습니다. 정확히는 3개의 패턴으로 다른 검색 정렬 결과가 나타났습니다.
지속적으로 검색 정렬이 바뀌는 이유는 elasticsearch에서는 데이터를 조회할때 shard 단위로 검색 요청을 보내게 되는데 이때 primary shard 와 replica shard를 elasticsearch의 내부적인 로직으로 선택을 하여 요청을 보내게 됩니다. 이러한 방식 때문에 사용자가 동일한 쿼리로 연속으로 두번 검색을 하게 되면 별도의 설정 없이는 동일한 샤드의 다른 복사본 샤드로 요청이 갈 가능성이 큽니다.
elasticsearch는 문서를 업데이트할때 수정이 필요한 특정 필드만 업데이트 하는 방식이 아니라 원본문서를 삭제 마킹 처리 후 업데이트 된 문서를 생성해내는 방식으로 동작합니다. 삭제처리 또한 즉시 문서를 삭제처리하지 않고 삭제 마킹 처리만 하여 검색결과에 노출되지 않게 됩니다.
elasticsearch는 이렇게 삭제 마킹처리된 문서들은 디스크에 남아있고 여전히 score를 계산할때 사용되는 인덱스 통계 수치에도 여전이 존재하게 됩니다. 그 후 백그라운드에서 주기적으로 또는 특정 임계치를 넘기면 더이상 필요없어진 문서들을 실제로 삭제처리하고(이때 인덱스 통계 수치에서도 제거됩니다) 여러 segment들을 새로운 큰 segment로 병합하게 됩니다.
이러한 segment 병합 과정은 각각의 shard마다 별개로 동작하기 때문에 인덱스 통계가 primary shard와 replica shard가 충분히 다를 수 있으므로 primary shard와 replica shard 들의 인덱스 통계가 모두 동일해지기 전까지는 검색 score도 지속적으로 변경될 가능성이 있습니다.
검색결과가 3개의 패턴으로 나타난 이유도 당시 상품 인덱스의 replica shard 설정이 2개로 되어 있어 1(primary shard) + 2(replica shard) = 3 개의 shard가 각각 다른 인덱스 통계를 가지고 있어 발생한 현상입니다.
elasticsearch 공식 문서에서 권장하는 방법으로는 검색 시 preference
라는 query parameter를 이용해 사용자의 세션ID(또는 사용자ID)를 넘겨줘 동일한 사용자에 대해서는 동일한 shard를 검색하게 하여 primary shard와 replica shard의 인덱스 통계가 다르더라도 동일한 검색 결과를 반환해주는 방법입니다.
preference
query parameter에는 여러가지 옵션들이 존재하는데 저는 위 문제를 해결하기 위해 custom-string
옵션을 사용하였습니다. custom-string
옵션은 preference 파라미터의 value에 해당하는 문자열에 따라 고정된 shard를 선택하게 해주는 옵션으로 value에 사용자의 세션ID를 입력해주면 고정된 shard를 검색하므로 동일 사용자에 대해서 동일한 검색 결과를 보여주게 됩니다.
참고자료