본문 바로가기
TIL/엘라스틱 서치

Elastic Search : Complete Guide to ElasticSearch - 낙관적 동시성 제어

by yeon_zoo 2024. 1. 14.

[도큐먼트 버저닝]

도큐먼트 버저닝은 과거의 버전으로 돌아갈 수 있다는 뜻은 아니다. 각 도큐먼트의 메타데이터 필드에 _version 값으로 저장한다. 

 

_version 값의 특징 (internal versioning)

  • 해당 값을 integer 형이다.
  • 도큐먼트를 수정할 때마다 1씩 증가한다. 
  • 도큐먼트를 삭제할 때는 60초간 유지한다. 
    • 같은 ID의 새 도큐먼트를 60초 내에 삽입하면 버전이 증가하고 아니면 reset 된다.

 

external versioning

  • 버전이 엘라스틱서치 밖에서 유지될 때 사용된다. 
  • ex) RDBMS에 도큐먼드가 저장될 때 등 (메인 DB로는 관계형 DB를, 검탐색을 위해서만 es를 사용하는 경우 등)

 

버저닝의 장점 

  • 도큐먼트가 수정된 횟수를 알 수 있다. (현재는 그렇게 유용한 정보가 아니다)
  • 과거에는 낙관적 동시성 제어의 방법 중에 하나였다. 
    • 지금은 primary term과 sequence number가 존재하기 때문에 versioning은 최고의 방법이 아니다. 

[낙관적 동시성 제어 (Optimistic Concurrency Control)]

  • 동시 연산으로 우연히 도큐먼트가 덮어써지는 것을 방지한다. 
  • 동시 연산은 다양한 시나리오에서 가능하다. 
    • ex) 이커머스 시스템 - 둘 이상의 사용자가 동시에 구매 transaction > 재고 - 1 처리하는 경우
    • 과거 처리 : 쿼리에 version을 붙이는 방식으로 해결 POST /products/_update/100?version=1
    • 현재 처리 : 쿼리에 parameter term & seq_no 붙이는 방식으로 해결
      POST /products/_update/100?if_primary_term=1&if_seq_no=71
      • 요청한 파라미터 값이 현재 도큐먼트와 맞지 않으면 에러를 뱉는다. 
      • 이 경우 애플리케이션 단에서 에러를 해결해야 한다. 
      • 도큐먼트를 다시 회복하고 새로운 업데이트 요청에 맞는 primary_term과 seq_no를 사용해야 한다. 

이커머스 시스템의 동시성 문제

 

과거 사용했던 동시성 문제를 해결하는 버저닝

[Update by Query]

  • 여러 도큐먼트를 한 번에 업데이트 하고 싶은 경우에 사용한다. (RDBMS의 UPDATE WHERE 절과 유사하다)
  • 아래 세 개념을 같이 사용하게 된다. 
    • primary terms
    • sequence number
    • optimistic concurrency control
  • 낙관적 동시성 제어를 위해 쿼리는 인덱스의 snapshot을 생성한다. 
  • Search query bulk request 순서대로 replication group 보내진다
    • 엘라스틱 서치는 최대 10번까지 해당 쿼리를 재시도한다. 
    • 10번 재시도 후에도 실패하면 전체 쿼리를 abort 시킨다. 단, 일부 replication group의 도큐먼트에 이미 진행된 변경사항이 있다면 그건 롤백하지 않는다. 
    • API는 실패에 대한 정보를 반환한다. 
    • 만약 도큐먼트가 스냅샷을 찍은 이후에 수정되었다면 쿼리가 aborted 된다. (primary term과 sequence number로 확인)
    • 쿼리를 abort 시키는 대신에 버전 충돌을 확인하고 싶다면 conflicts 옵션을 proceed로 변경하면 된다. 

 

[Delete by Query]

  • Update by query 와 비슷하게 여러 도큐먼트를 하나의 쿼리를 이용해서 변경한다. 
  • ex) 
// 아래 쿼리 실행 시 인덱스 내 모든 도큐먼트 삭제 됨
POST /products/_delete_by_query
{
	"query": {
    	"match_all": {}
    }
}

댓글