인덱스의 샤드 개수(number_of_shards) 는 한 번 지정하면 reindex 등의 특별한 작업을 수행하지 않는 한 변경할 수 없다.
그런데 샤드 개수를 어떻게 지정하느냐에 따라 엘라스틱서치 클러스터 전체의 성능이 크게 달라진다. 중요한 설정임에도 불구하고 샤드 개수를 정확히 어떤 값으로 지정하면 되는지 딱 정해주는 알기 쉽고 명확한 기준은 알려진 바가 없다. 이 문제는 굉장히 어려운 문제다. 이번 절에서는 샤드 개수를 어떻게 지정할지 그 전략을 알아보도록 하겠습니다.
샤드 크기와 개수 조정
클러스터에 샤드 숫자가 너무 많아지면 클러스터 성능이 눈에 띄게 떨어지게 됩니다. 샤드 하나당 루씬 인덱스가 하나씩 더 뜨며 힙을 차지 한다. 주 샤드를 하나 더 띄울 때마다 복제본 샤드도 늘어나는 것을 고려하면 무작정 number_of_shards를 늘릴 수는 없다. 그렇다고 샤드 숫자를 적게 지정하면 샤드 하나당 크기가 커진다.
샤드 하나의 크기가 너무 커지는것도 심각한 문제이고, 샤드 크기가 지나치게 크면 재기동이나 장애 상황 등에서 샤드 복구, 복제본 샤드 생성에 너무 많은 시간이 소요된다. 이렇게 되면 문제 상황에서 클러스터 안정성이 크게 떨어진다. 장애로 인해 재기동한 노드가 샤드 복구를 하는 과정 자체가 너무 무거워서 복구 도중 다시 죽는 일도 생길 수 있다. 전체 적인 서비스 성능도 쉽게 체감될 정도로 감소한다.
결국 밸런스가 중요합니다.
그렇다면 어떤 기준으로 어떻게 밸런스를 잡아야 할까요?
조금 더 중요한 원칙은 샤드 하나의 크기를 일정 기준 이하로 유지해야한다는 것입니다.
전체 샤드의 수를 체크 하는 것은 그 다음입니다.
샤드의 크기를 기준 크기 이하로 유지하는 선에서 전체 샤드 개수를 최대한 줄이는 방향으로 접근 해야합니다. 그렇다면 '너무 크다'의 기준은 얼마나 되어야 할까요?? ( 엘라스틱 블로그 참조 : 샤드 당 20GB~ 40GB 크기가 적절하다고 말하고있음), 그러나 실제 운영 경험상으로는 샤드 하나당 크기가 20GB 만 되어도 다양한 상황에서 느리고 무겁다라고 느껴집니다.
블로그에서 말한 크기의 샤드 또한 버틸 수 있을지 모르지만, 수 GB 내외 수준에서 조정하는 것을 추천드립니다.
샤드의 크기는 cat shards API 를 이용해서 확인 할 수 있습니다.
GET _cat/shards?v&s=store:desc
또한 블로그에서 힙 1GB 당 20개 이하의 샤드를 들고있는 것이 적절하다고 설명하고 약 32GB 힙 기준으로 노드당 640 샤드 이하다.
샤드 개수 확인 API
GET _cat/health?v
GET _cat/allocation?v
힙 1GB 당 샤드 20개 기준은 빡빡하기는 하나 이 기준을 지키는 것을 어느 정도 이상적인 목표로 삼으며 밸런스를 조정하면 좋다.
그러나 이 기준만으로 샤드 개수를 결정할 수는 없다. 샤드 개수 결정에 고려하면 좋은것을 더 알아보도록 하자.
모든 노드가 충분히 일을 하고 있는지...?
ES 의 샤드는 이름 자체가 의미하듯 샤딩, 즉 분산처리를 위해 생긴 개념이다.
전체 샤드 개수를 줄이는 것만 생각하다 보면 분산처리의 강점을 충분히 살리지 못할 수도 있다. 특정인덱스의 주 샤드와 복제본 샤드가 모든 노드에 고르게 퍼지도록 설정하는 것도 중요한 요소다. 노드 대수가 n대라면 number_of_shards를 n의 배수로 지정해 모든 노드가 작업을 고르게 분산받도록 설정하는 방법 등의 사용된다. 특히 서비스 중요도가 높은 인덱스나 성능을 타이트하게 조정해야 하는 인덱스라면 이 부분을 신경 써야 한다.
서비스상 빈번하게 호출되지 않느 ㄴ인덱스나 크기가 너무 작은 인덱스의 샤드를 모든 노드에 배치 시킬 필요는 없다.
n의 배수에도 크게 집착하지 않아도 된다. 어차피 추후 선형적 확장을 위해 추가 서버가 투입되면 이 숫자가 달라지게 된다. 또한 한 엘라스틱서치 클러스터에서 활발하게 작업 중이 ㄴ인덱스의 수가 이미 충분히 많다면 단일 인덱스에 대해 모든 노드가 일을 하고 있는지를 과도하게 신경 쓸 필요가 없을 수도 있다. 한 인덱스의 작업에 참혀하지 않는 노드이더라도 다른 인덱스의 작업에 리소스를 사용할 것이기 때문이다. 서비스 중요도와 함께 샤드의 크기, 개수 등의 요소를 함께 적절히 고려한 중용이 필요하다.
미래에 데이터가 커질 것을 고려
지금은 데이터가 초당 n개 씩 들어오지만 한두 달 사이에 초당 10n 개의 데이터가 인입될 수 도 있다. 서비스 요건상 데이터의 성질이 변경되어 새로운 필드가 많이 추가되거나 데이터 크기 자체가 커질 수 있다. 이런 운영상의 이슈로 인해 미래에 커질 수 있는 데이터 사이즈를 어느 정도 고려해서 설정해야 한다.
인덱스 이름에 시간값을 넣어 정기적으로 신규 인덱스를 생성하는 성질의 데이터는 템플릿에 설정된 number_of_shards 값을 봐 가면서 변경하면 이런 문제를 어느 정도 유연하게 대처할 수 있다.
그러나 단일 인덱스에 서비스 데이터를 담고 있다면 그렇게 하기는 어렵다. 이런 경우라면 미레에 커질 데이터 사이즈를 넉넉히 예상해서 설정해 두는 것이 좋다. 그렇더라도 버틸 수 없는 상태 까지 오면 결국 reindex를 할 수 밖에 없다. reindex를 위해서 미리 alias 를 설정해 두는 것을 잊지 않아야한다.
테스트 수행
앞선 요소들은 단순하게 일률적으로 적용될 만한 것은 아미녀 서비스 환경마다 상황이 다르다. 즉 엘라스틱 블로그에 실힌 힙 1gb당 샤드 2-개라는 가이드 또한 데이터 특성을 전혀 고려하지 않는 숫자입니다. 실제로는 인덱스에 어떤 성격의 데이터가 얼마나 있는지에 따라 양상이 매우 다릅니다. 여러 통제된 조건에서 테스트를 해 보고 결정하는 것이 좋습니다.
특히 성능에 민감한 인덱스라면 테스트가 더더욱 중요합니다.
가능하다면 실제 서비스 조건과 유사한 조건으로 테스트를 수행해 보고 그 결과를 참고해 개수를 지정하도록 하자.
물론 문제를 많이 일으키는 인덱스는 데이터 양과 특성이 자주 바뀌는 인덱스인 경우가 많다.
다양한 요소를 잘 고려해서 종합적으로 결정해야 합니다.
'Elasticsearch' 카테고리의 다른 글
엘라스틱서치 - 장애 복구 작업 도중 새 인덱스 생성될 때 (0) | 2023.10.04 |
---|---|
엘라스틱서치 - 대량 색인이 필요할 때 (0) | 2023.10.01 |
엘라스틱서치(Elasticsearch) - 동시성 제어 (0) | 2023.09.19 |
엘라스틱서치에서 인덱스 생명주기 (elasticsearch- index_lifeCycle management) 설정 (1) | 2023.08.23 |
엘라스틱서치 샤드 재배치 (elasticsearch Shard relocation) (0) | 2023.08.03 |