고급 검색 마이그레이션 스타일 가이드
새로운 고급 검색 마이그레이션 생성
참고: 이 기능은 GitLab 13.0 및 이후에 생성된 인덱스에서만 지원됩니다.
스크립트를 사용하여
- 소개: GitLab 16.3에서 소개되었습니다.
scripts/elastic-migration
을 실행하고 프롬프트에 따라 다음을 생성하세요:
- 마이그레이션을 정의하는 마이그레이션 파일:
ee/elastic/migrate/YYYYMMDDHHMMSS_migration_name.rb
- 마이그레이션을 테스트하는 스펙 파일:
ee/spec/elastic/migrate/YYYYMMDDHHMMSS_migration_name_spec.rb
- 마이그레이션을 식별하는 사전 파일:
ee/elastic/docs/YYYYMMDDHHMMSS_migration_name.yml
수동으로
- 소개: GitLab 13.6에서 소개되었습니다.
ee/elastic/migrate/
폴더에서 YYYYMMDDHHMMSS_migration_name.rb
파일 형식의 새 파일을 만듭니다. 이 형식은 Rails 데이터베이스 마이그레이션과 동일합니다.
# frozen_string_literal: true
class MigrationName < Elastic::Migration
# 중요: Elastic 인덱스 매핑에 대한 모든 업데이트는 각각의 구성 파일에서 복제되어야 합니다:
# - 메인 인덱스를 위한 `Elastic::Latest::Config`
# - 독립형 인덱스를 위한 `Elastic::Latest::<Type>Config`
def migrate
end
# 마이그레이션이 완료되었는지 확인합니다
# 완료되었으면 true를 반환하고, 그렇지 않으면 false를 반환합니다
def completed?
end
end
적용된 마이그레이션은 gitlab-#{RAILS_ENV}-migrations
인덱스에 저장됩니다. 실행되지 않은 모든 마이그레이션이 Elastic::MigrationWorker
크론 워커에 의해 순차적으로 적용됩니다.
Elastic 인덱스 매핑을 업데이트하려면 해당 파일에 구성을 적용하세요:
- 메인 인덱스의 경우:
Elastic::Latest::Config
. - 독립형 인덱스의 경우:
Elastic::Latest::<Type>Config
.
마이그레이션은 재시도 한도와 실패하여 중단된 것으로 표시될 수 있는 기능을 갖추고 있습니다. 마이그레이션 재시도를 지원하기 위해 필요한 모든 데이터 또는 인덱스 정리는 마이그레이션에서 처리되어야 합니다.
마이그레이션 도우미
다음의 마이그레이션 도우미는 ee/app/workers/concerns/elastic/
에 사용 가능합니다:
Elastic::MigrationBackfillHelper
인덱스에서 특정 필드를 백필합니다. 대부분의 경우 필드 매핑은 이미 추가되어야 합니다.
단일 필드를 백필하려면 field_name
메서드와 DOCUMENT_TYPE
상수가 필요합니다.
class MigrationName < Elastic::Migration
include Elastic::MigrationBackfillHelper
DOCUMENT_TYPE = Issue
private
def field_name
:schema_version
end
end
하나 이상의 필드가 널이면 여러 필드를 백필하려면 field_names
메서드와 DOCUMENT_TYPE
상수가 필요합니다.
class MigrationName < Elastic::Migration
include Elastic::MigrationBackfillHelper
DOCUMENT_TYPE = Issue
private
def field_names
%w[schema_version visibility_level]
end
end
Elastic::MigrationUpdateMappingsHelper
매핑을 업데이트하여 지정된 매핑으로 put_mapping
을 호출합니다.
new_mappings
메서드와 DOCUMENT_TYPE
상수가 필요합니다.
class MigrationName < Elastic::Migration
include Elastic::MigrationUpdateMappingsHelper
DOCUMENT_TYPE = Issue
private
def new_mappings
{
schema_version: {
type: 'short'
}
}
end
end
Elastic::MigrationRemoveFieldsHelper
인덱스에서 지정된 필드를 제거합니다.
index_name
, document_type
메서드가 필요합니다. 제거할 필드가 하나인 경우 field_to_remove
메서드를 추가하고, 그 외에는 배열 형식의 fields_to_remove
를 추가합니다.
document_type
와 일치하는 문서가 지정된 필드를 Elasticsearch에서 가지고 있는지 일괄적으로 확인합니다. 문서가 존재하는 경우 Painless 스크립트를 사용하여 update_by_query
를 수행합니다.
class MigrationName < Elastic::Migration
include Elastic::MigrationRemoveFieldsHelper
batched!
throttle_delay 1.minute
private
def index_name
User.__elasticsearch__.index_name
end
def document_type
'user'
end
def fields_to_remove
%w[two_factor_enabled has_projects]
end
end
기본 일괄 크기는 10,000
입니다. 이 값을 BATCH_SIZE
로 지정하여 재정의할 수 있습니다.
class MigrationName < Elastic::Migration
include Elastic::MigrationRemoveFieldsHelper
batched!
BATCH_SIZE = 100
...
end
Elastic::MigrationObsolete
필요하지 않을 때 마이그레이션을 사용하지 않게 표시합니다.
class MigrationName < Elastic::Migration
include Elastic::MigrationObsolete
end
Elastic::MigrationCreateIndex
새로운 색인을 생성합니다.
필요 사항:
-
target_class
및document_type
메서드 -
ee/lib/elastic/latest/
및ee/lib/elastic/v12p1/
내의 클래스에 대한 매핑 및 색인 설정
경고: 동일한 마일스톤에서 색인을 채우기 위한 후속 마이그레이션을 수행해야 합니다.
class MigrationName < Elastic::Migration
include Elastic::MigrationCreateIndex
retry_on_failure
def document_type
:epic
end
def target_class
Epic
end
end
Search::Elastic::MigrationReindexBasedOnSchemaVersion
지정된 문서 유형을 저장하는 색인에 있는 모든 문서를 재색인하고 schema_version
을 업데이트합니다.
DOCUMENT_TYPE
및 NEW_SCHEMA_VERSION
상수가 필요합니다.
색인 매핑에는 YYMM
형식의 schema_version
정수 필드가 있어야 합니다.
class MigrationName < Elastic::Migration
include Search::Elastic::MigrationReindexBasedOnSchemaVersion
batched!
batch_size 9,000
throttle_delay 1.minute
DOCUMENT_TYPE = WorkItem
NEW_SCHEMA_VERSION = 23_08
UPDATE_BATCH_SIZE = 100
end
Search::Elastic::MigrationDeleteBasedOnSchemaVersion
지정된 문서 유형을 저장하는 색인에서 schema_version
이 주어진 값보다 작은 모든 문서를 삭제합니다.
DOCUMENT_TYPE
상수와 schema_version
메서드가 필요합니다.
색인 매핑에는 YYMM
형식의 schema_version
정수 필드가 있어야 합니다.
class MigrationName < Elastic::Migration
include ::Search::Elastic::MigrationDeleteBasedOnSchemaVersion
DOCUMENT_TYPE = Issue
batch_size 10,000
batched!
throttle_delay 1.minute
retry_on_failure
def schema_version
23_12
end
end
Search::Elastic::MigrationDatabaseBackfillHelper
데이터베이스의 모든 문서를 limited_indexing
설정을 준수하여 Elastic Search 색인에 다시 색인합니다.
DOCUMENT_TYPE
상수와 respect_limited_indexing?
메서드가 필요합니다.
class MigrationName < Elastic::Migration
include ::Search::Elastic::MigrationDatabaseBackfillHelper
batch_size 10,000
batched!
throttle_delay 1.minute
retry_on_failure
DOCUMENT_TYPE = Issue
def respect_limited_indexing?
true
end
end
Elastic::MigrationHelper
이전 예제에 맞지 않는 마이그레이션을 처리할 때 사용할 수 있는 메서드를 포함합니다.
class MigrationName < Elastic::Migration
include Elastic::MigrationHelper
def migrate
...
end
def completed?
...
end
end
Elastic::MigrationWorker
가 지원하는 마이그레이션 옵션
Elastic::MigrationWorker
는 다음 마이그레이션 옵션을 지원합니다:
-
batched!
- 마이그레이션을 일괄 처리로 실행할 수 있도록 허용합니다. 설정된 경우,Elastic::MigrationWorker
자체를throttle_delay
옵션으로 설정된 지연 시간으로 다시 대기열에 넣습니다. 일괄처리는migrate
메서드에서 처리해야 합니다. 이 설정은 다시 대기열에 대해서만 제어합니다. -
batch_size
-batched!
마이그레이션 실행 중 수정된 문서 수를 설정합니다. 이 크기는 업데이트에 충분한 시간을 제공하는 값이어야 합니다. 이는 아래 설명된throttle_delay
옵션과 조합하여 튜닝할 수 있습니다. 일괄 처리는 사용자 정의migrate
메서드에서 처리하거나Elastic::MigrationBackfillHelper
이 설정을 사용하는migrate
메서드를 통해 조정될 수 있습니다. 기본값은 1000입니다. -
throttle_delay
- 일괄 처리 간의 대기 시간을 설정합니다. 각 마이그레이션 일괄 처리가 충분한 시간을 제공할 수 있도록 설정해야 합니다. 또한 이 시간은 5분보다 짧아야 합니다. 왜냐하면Elastic::MigrationWorker
cron 작업이 동작하는 주기이기 때문입니다. 기본값은 3분입니다. -
pause_indexing!
- 마이그레이션이 실행될 때 색인을 일시 중지합니다. 이 설정은 마이그레이션이 완료될 때 원래의 색인 설정을 기록하고 다시 설정합니다. -
space_requirements!
- 마이그레이션이 실행될 때 클러스터에 충분한 여유 공간이 있는지 확인합니다. 이 설정은 마이그레이션이 실행될 때 필요한 저장 공간이 없는 경우 마이그레이션을 중지시킵니다. 마이그레이션은space_required_bytes
메서드를 통해 필요한 공간을 제공해야 합니다. -
retry_on_failure
- 실패 시 재시도 기능을 활성화합니다. 기본적으로 30번의 재시도를 수행한 후 마이그레이션이 중단됩니다. 재시도 횟수를 사용자 정의하려면max_attempts
매개변수를 전달하세요:retry_on_failure max_attempts: 10
# frozen_string_literal: true
class BatchedMigrationName < Elastic::Migration
# 마이그레이션을 일괄 처리로 실행할 것임을 선언합니다.
batched!
throttle_delay 10.minutes
pause_indexing!
space_requirements!
retry_on_failure
# ...
end
다운 타임 방지
마이그레이션 되돌리기
만약 마이그레이션이 실패하거나 GitLab.com에서 중단된 경우, 마이그레이션을 도입한 변경 사항을 되돌리는 것을 선호합니다. 이렇게 함으로써 Self-Managed 고객이 손상된 마이그레이션을 받지 않게 되고 백포트(backport)가 필요한 경우가 줄어듭니다.
병합 시기
릴리즈 후 1주일 이내에 마이그레이션을 병합하는 것을 선호하지 않습니다. 이렇게 함으로써 마이그레이션이 실패하거나 예상대로 작동하지 않는 경우를 대비하는 시간을 확보할 수 있습니다. 릴리즈의 최종 주에 개발 중이거나 검토 중인 마이그레이션은 다음 마일스톤으로 미루어져야 합니다.
다중 버전 호환성
다른 GitLab 변경 사항처럼 고급 검색 마이그레이션도 동시에 여러 버전의 애플리케이션이 실행 중인 경우를 지원해야 합니다. (다중 버전 호환성 참조)
배포 순서에 따라, 마이그레이션이 시작되었거나 완료되었고 마이그레이션 이전 애플리케이션 코드를 실행 중인 서버가 있는 경우가 가능합니다. 이러한 점을 고려하여 모든 고급 검색 마이그레이션이 배포가 완료된 후에 시작될 수 있도록 보장해야 합니다.
고위험 마이그레이션
Elasticsearch가 트랜잭션을 지원하지 않기 때문에, 마이그레이션이 시작되거나 완료된 후에 애플리케이션 코드가 되돌아가는 상황을 고려해야 합니다.
이러한 이유로 파괴적인 작업(예: 데이터 이동 후 삭제)은 일반적으로 마이그레이션이 성공적으로 완료된 후 다음 병합 요청으로 연기해야 합니다. Self-Managed 고객의 경우 중요한 데이터 손실이 발생할 수 있는 경우 릴리즈를 미루어 다음 릴리즈로 연기해야 합니다.
마이그레이션 실행 시간 계산
GitLab.com에서 마이그레이션이 실행되는 데 소요되는 시간을 이해하는 것은 중요합니다. 마이그레이션에 의해 처리될 문서 수를 파생할 수 있습니다. 이 숫자는 데이터베이스 또는 기존 Elasticsearch 인덱스를 쿼리하여 얻을 수 있습니다. 다음 공식을 사용하여 실행 시간을 계산하십시오:
> batch_size = 9_000
=> 9000
> throttle_delay = 1.minute
=> 1 minute
> number_of_documents = 15_536_906
=> 15536906
> (number_of_documents / batch_size) * throttle_delay
=> 1726 minutes
> (number_of_documents / batch_size) * throttle_delay / 1.hour
=> 28
고급 검색 마이그레이션을 위한 모범 사례
최상의 결과를 얻기 위해 다음의 모범 사례를 따르십시오:
- 각 문서 유형별로 모든 마이그레이션을 순서화하여,
Elastic::MigrationUpdateMappingsHelper
를 사용하는 마이그레이션을 사용하는 마이그레이션들이Elastic::MigrationBackfillHelper
를 사용하는 마이그레이션보다 먼저 실행되도록 합니다. 이렇게 함으로써 모든 마이그레이션이 적용되지 않은 상태에서 동일한 문서를 다수 번 재색인하는 것을 피하고 백필(backfill) 시간을 줄일 수 있습니다. - 배치 작업 시, 배치 크기를 9,000개 미만으로 유지하십시오. 대량 색인기는 1분마다 실행되며 여기서 10,000개의 문서를 처리합니다. 따라서 대량 색인기가 다음 마이그레이션 배치를 시도하기 전에 레코드를 처리할 시간을 확보할 수 있습니다.
- 마이그레이션이 완료되었는지 확인하기 전에 인덱스를 새로고침해야 합니다.
- 각 마이그레이션 시작 시, 완료 확인이 발생할 때, 마이그레이션이 완료될 때마다 로깅 문을 추가하십시오. 이러한 로그는 마이그레이션 문제를 디버깅할 때 유용합니다.
- Elasticsearch Reindex API 작업을 사용하는 경우 색인 작업을 일시 중지하십시오.
- 마이그레이션 실패 가능성이 있는 경우 재시도 제한을 설정하는 것을 검토하십시오. 이렇게 하면 문제가 발생할 경우 마이그레이션을 중지할 수 있습니다.
주요 버전 업그레이드 시 고급 검색 마이그레이션 삭제
일반적으로 고급 검색 마이그레이션은 장기간에 걸쳐 여러 코드 경로를 지원해야 하므로, 안전하게 삭제할 수 있는 시기에 제거하는 것이 중요합니다.
GitLab 주요 버전 업그레이드를 안전한 시기로 선택하여 완전히 마이그레이션되지 않은 인덱스의 역호환성을 제거하는 것을 선택합니다. 이에 관한 내용은 업그레이드 문서에서 문서화되어 있습니다. 또한, 멈춰진 마이그레이션 코드를 제거하고 테스트를 제거하여:
- 고급 검색 마이그레이션에서 호출되는 코드를 유지할 필요가 없습니다.
- 더 이상 지원하지 않는 마이그레이션에 대한 테스트를 실행하는 데 시간을 낭비할 필요가 없습니다.
- 이러한 마이그레이션이 실행되지 않은 연산자가 대상 버전으로 직접 업그레이드하는 경우 다시 처음부터 색인 작업을 진행할 것을 요구하는 메시지가 표시됩니다.
더해, 매우 안전하게 제거하려면 주요 업그레이드 직전의 마이너 버전에서만 추가된 마이그레이션을 제거하지 않습니다. 예를 들어, %14.0
으로 업그레이드하는 경우 %13.12
에서만 추가된 마이그레이션을 제거하면 안됩니다. 이러한 추가적인 안전장치를 통해 GitLab.com에서 여러 주간 걸릴 수 있는 마이그레이션에 대비할 수 있습니다. GitLab.com 배포는 자동화되어 있으며 이를 방지하는 자동화된 검사가 없으므로 추가적인 주의가 필요합니다. 게다가, 만일 해당 자동화된 검사가 있더라도 고급 검색 마이그레이션을 GitLab.com 배포를 지연시키고 싶지 않을 것이므로, 이러한 마이그레이션은 종종 1주일의 추가 기간이 필요하기 때문에 실제로는 GitLab.com 배포를 차단할 필요가 없습니다.
마이그레이션을 오래 되었다고 표시하는 프로세스
주요 버전을 업그레이드하기 2개의 마이너 버전 전에 생성된 모든 마이그레이션에 대해 우리는 다음을 합니다:
- 마이그레이션이 GitLab.com에서 실제로 성공적으로 완료되었는지 확인합니다.
-
마이그레이션 내용을 다음으로 대체합니다:
include Elastic::MigrationObsolete
- 이 마이그레이션을 지원하는 모든 spec 파일을 삭제합니다.
-
.rubocop_todo/
디렉토리에서 이 마이그레이션에 대한 참조가 없는지 확인합니다. - 이 마이그레이션에 대한 역 호환성 처리를 제거합니다.
이를 찾으려면
Elastic::DataMigrationService.migration_has_finished?(:migration_name_in_lowercase)
를 찾으면 됩니다. - 이러한 변경으로 병합 요청을 작성합니다. 우리가 주요 릴리스가 시작되기 전에 이를 실수로 병합하지 않도록 주의하세요.
마이그레이션 제거 프로세스
- 현재 주요 릴리스 이전에 폐기로 표시된 마이그레이션을 선택합니다.
- 위 단계에 모든 폐기 마이그레이션이 포함되면, 적용되지 않은 마이그레이션을 가진 고객들을 위한 안전장치로 마지막 마이그레이션을 유지합니다.
- 해당 마이그레이션 파일 및 spec 파일을 삭제합니다.
-
.rubocop_todo/
디렉토리에서 해당 마이그레이션에 대한 참조가 없는지 확인합니다. - 병합 요청을 생성하고 그것을 글로벌 검색 팀의 팀원에게 할당합니다.