elasticsearchshard split 사고

4582 단어
앞의 몇 편의 글은 코드 차원에서elasticsearch 내부에서shardsplit을 어떻게 실현하는지 소개했는데 이 글은 주로 두 가지 질문에 대답한다.
  • 왜 하나의shard만 분할할 수 없는지
  • split 후 데이터 분포식이 일치하는 것을 어떻게 보장합니까? 즉, 원래의 데이터에 대해 다시hash를 하지 않아도 됩니다

  • 우선,elasticsearch는hash의 방식을 통해 모든 문서가 속한 조각을 확정합니다.
    hash(docId) % numShards
    그 중에서docId는 어떤 문서의 id를 나타내고numShards는 색인이 몇 개의shard인지 나타낸다.그러면 문제가 생겼습니다. split 후shard 개수가 바뀌었습니다. 문서마다hash 후shard 개수에 대한 모델링도 틀림없이 달라질 것입니다.열을 들어라: 원래 두 개의shard가 있고 네 개의 문서가 있다고 가정하면hash 후의 문서 id는 각각 0, 1, 2, 3이다.그러면 이 네 개의 문서가 elasticsearch에 저장되면 이런 상황이 됩니다.
    Sshard0: 0, 2 Sshard1: 1, 3
    각각shard는 두 개의 문서를 포함합니다.만약 현재 split가 네 개의shard가 된다면, 원본 인덱스의shardsplit가 목표 인덱스의 두 개의shard가 됩니다.그러면 대상shard와 원본shard의 관계는 다음과 같다.
    Tshard0 -> Sshard0 Tshard1 -> Sshard0 Tshard2 ->Sshard1 Tshard3 -> Sshard1
    그 중에서 Tshard는 목표shard를 나타내고 Sshard는 원본shard를 나타낸다.이전 몇 편의 글에서 목표shard를 선택한 원본shard 알고리즘은 다음과 같다는 것을 알았기 때문이다.
    Sshard = Tshard/routingFactor routingFactor = numTargetShard/numSourceShard
    이런 상황에서routingFactor=2.그런데 이렇게 스플릿은 안 될 것 같아!만약 해시 모드에 따라shard를 확정한다면, 문서 1이 목표 인덱스에 속한shard는 1퍼센트 4=1이어야 합니다.할당 상황은 다음과 같습니다.
    Tshard0: 0 Tshard1: 1 Tshard: 2 Tshard: 3
    즉, 문서 1은 대상 Tshard1에 있고 Tshard1은 Sshard0 split를 통해 얻을 수 있습니다.하지만 Sshard0에는 문서 1이 없습니다.그럼 elasticsearch는 어떻게 이 문제를 해결했습니까?split를 지원하려면 두 가지 제한 조건이 있습니다. 하나는 색인을 만들 때number_를 지정해야 한다는 것입니다.of_routing_shards 매개 변수.그렇다면 이 매개 변수는 구체적으로 어떤 작용을 합니까?먼저 뒤에 shardId를 생성하는 알고리즘을 보겠습니다.
    OperationRouting
    public static int generateShardId(IndexMetaData indexMetaData, @Nullable String id, @Nullable String routing) {
            final String effectiveRouting;
            final int partitionOffset;
    
            if (routing == null) {
                assert(indexMetaData.isRoutingPartitionedIndex() == false) : "A routing value is required for gets from a partitioned index";
                effectiveRouting = id;
            } else {
                effectiveRouting = routing;
            }
    
            if (indexMetaData.isRoutingPartitionedIndex()) {
                partitionOffset = Math.floorMod(Murmur3HashFunction.hash(id), indexMetaData.getRoutingPartitionSize());
            } else {
                // we would have still got 0 above but this check just saves us an unnecessary hash calculation
                partitionOffset = 0;
            }
    
            return calculateScaledShardId(indexMetaData, effectiveRouting, partitionOffset);
        }
    

    이 함수는shardId를 생성하는 알고리즘입니다. id 매개 변수는 문서 id이고routing 매개 변수는 사용자 정의 루트의 매개 변수입니다.사용자 정의 루트가 있으면shard를 확인하기 위해 문서 id를 사용하지 않을 것입니다.
    private static int calculateScaledShardId(IndexMetaData indexMetaData, String effectiveRouting, int partitionOffset) {
            final int hash = Murmur3HashFunction.hash(effectiveRouting) + partitionOffset;
    
            // we don't use IMD#getNumberOfShards since the index might have been shrunk such that we need to use the size
            // of original index to hash documents
            return Math.floorMod(hash, indexMetaData.getRoutingNumShards()) / indexMetaData.getRoutingFactor();
        }
    

    여기에서hash값을 추출한 후routingFactor를 제외하고는그리고numShards에 대한 모드가 아니라routingNumShards에 대한 모드입니다.IndexMetaData.getRoutigNumShards는 색인을 만들고 지정한number_of_routing_shards 값, IndexMetaData.get Routing Factor의 값은 사실routing NumShards/number OfShards입니다.여기서 실용적인 것은 일치성 해시 알고리즘입니다. 해시 공간은routingNumShards 매개 변수로 지정됩니다. 인덱스를 만들 때number_를 지정하지 않으면of_routing_shards 매개 변수는 routingNumShards의 값이numberOfShards와 같습니다.그래서 split이 왜 숫자를 지정해야 하는지 알겠어요_of_routing_shards 매개 변수, 그리고 split의 최대 횟수는 이 매개 변수에 제한됩니다.이제 위의 예를 다시 한 번 보십시오. 색인을 만들 때number_of_routing_shards는 8,shard수는 2,그럼.할당 상황은 다음과 같습니다.
    routingNumShards=8,numberOfShards=2, routingFcator = 4 Sshard0: 0,1,2,3 (0 % 8)/4 = 0, (1%8)/4 = 0, (2%8)/4 = 0 , (3%8)/4 = 0 Sshard1:
    모든 문서가 Sshard0에 할당되어 있음을 볼 수 있습니다.그리고 지금 분열이 필요합니까, 아니면 네 개의shard로 분열해야 합니까?주의해야 할 것은 분열할 때도routingFactor가 있는데 두 routingFactor의 차이를 분명히 해야 한다.분열 후shard 간의 대응 관계는 여전히 변하지 않았다.
    Tshard0 -> Sshard0 Tshard1 -> Sshard0 Tshard2 ->Sshard1 Tshard3 -> Sshard1
    분열 후 목표 인덱스의routingNumShards 값은 원본 인덱스와 같기 때문에 8, 단일 목표 인덱스의shard수 변수이기도 하다. 최종 목표 인덱스 분배 상황은 다음과 같다.
    routingNumShards=8,numberOfShards=4, routingFcator = 2 Tshard0: 0, 1 (0 % 8)/2 = 0, (1 % 8)/2 = 0 Tshard1: 2, 3 (2 % 8)/2 = 1, (3 % 8 )/2 = 1 Tshard2: Tshard3:
    이렇게 해서 Sshard0은 Tshard0, Tshard1로 분열되면 문제없다.이 문제를 해결했지만 이런 방법은 split할 때 에너지 인덱스의 모든shard가 split에 참여하고 단독의shardsplit를 지원하지 않게 한다.shardId를 계산할 때 모델을 추출한 결과routingFactor를 제외하고는 각각shard가hash공간에 있는 각각의 통을 평균적으로 분배하는 셈이기 때문에 어떤shard가 차지하는hash통이 비교적 많은 상황이 나타날 수 없다.

    좋은 웹페이지 즐겨찾기