CI 미러 테이블
문제 진술
데이터베이스 분해 작업의 일환으로,
GitLab이 사용하는 단일 데이터베이스를 main
과 ci
두 개의 데이터베이스로 분할하는 목표가 있었으며,
이와 관련하여 main
과 ci
테이블 간의 모든 조인을 제거하는 큰 도전이 있었습니다.
이는 PostgreSQL이 서로 다른 데이터베이스에 속하는 테이블 간의 조인을 지원하지 않기 때문입니다.
하지만 메인 데이터베이스의 일부 핵심 애플리케이션 모델은 CI 측에 의해 매우 자주 쿼리됩니다. 예를 들어:
-
Namespace
,namespaces
테이블에서. -
Project
,projects
테이블에서.
이 테이블들에서 joins
를 수행할 수 없다는 것은 큰 도전 과제가 됩니다. 팀은 이러한 테이블들의 논리적 복제를
메인 데이터베이스에서 CI 데이터베이스로 새 테이블에 수행하기로 선택했습니다:
-
ci_namespace_mirrors
,namespaces
테이블의 미러로 -
ci_project_mirrors
,projects
테이블의 미러로
이 논리적 복제는 두 가지 의미를 가집니다:
-
main
데이터베이스 테이블을 쿼리하고namespaces
및projects
테이블에 조인할 수 있습니다. -
ci
데이터베이스 테이블은ci_namespace_mirrors
및ci_project_mirrors
테이블과 조인할 수 있습니다.
이 복제는 각 모델에서 필요한 몇 가지 속성으로 제한되었습니다:
-
Namespace
에서traversal_ids
를 복제합니다. -
Project
에서는 프로젝트가 속한 그룹을 나타내는namespace_id
만 복제합니다.
CI 미러 테이블을 소스 테이블과 동기화 유지하기
우리는 소스와 대상 테이블을 동기화하기 위해 두 가지 유형의 이벤트에 주의해야 합니다:
- 새로운 namespaces 또는 projects의 생성.
- namespaces 또는 projects의 업데이트.
- namespaces/projects의 삭제.
생성 및 업데이트
새로 생성되거나 업데이트된 네임스페이스 또는 프로젝트의 데이터 동기화는 다음과 같은 순서로 진행됩니다:
-
main
데이터베이스에서:namespaces
또는projects
테이블에서의 모든INSERT
또는UPDATE
는namespaces_sync_events
와projects_sync_events
테이블에 항목을 추가합니다. 이 테이블들은main
데이터베이스에도 존재합니다. 이러한 항목은 두 테이블의 트리거에 의해 추가됩니다. -
모델 수준에서:
Namespace
또는Project
소스 모델 중 하나에 커밋이 발생하면, 해당하는 Sidekiq 작업Namespaces::ProcessSyncEventsWorker
또는Projects::ProcessSyncEventsWorker
가 실행되도록 예약됩니다. -
이러한 작업자들은 다음을 수행합니다:
-
main
데이터베이스의(namespaces/project)_sync_events
테이블에서 항목을 읽어, 동기화할 네임스페이스 또는 프로젝트를 확인합니다. - 업데이트된 레코드의 데이터를 타겟 테이블
ci_namespace_mirrors
,ci_project_mirrors
로 복사합니다.
-
삭제
namespaces
또는 projects
가 삭제되면, 미러링된 CI 테이블의 타겟 레코드는 느슨한 외래 키 (LFK) 메커니즘을 사용하여 삭제됩니다.
config/gitlab_loose_foreign_keys.yml
에 이러한 항목이 있기 때문에, LFK 메커니즘은 이미 기대한 대로 작동하고 있었습니다. 이는 main
데이터베이스에서 삭제된 namespaces
또는 projects
에 매핑된 CI 미러링 테이블의 모든 레코드를 삭제했습니다.
ci_namespace_mirrors:
- table: namespaces
column: namespace_id
on_delete: async_delete
ci_project_mirrors:
- table: projects
column: project_id
on_delete: async_delete
일관성 검사
두 동기화 메커니즘이 정상적으로 작동하도록 하기 위해, 우리는 몇 분마다 크론 작업에 의해 트리거되는 두 개의 추가 작업자를 배포합니다:
Database::CiNamespaceMirrorsConsistencyCheckWorker
Database::CiProjectMirrorsConsistencyCheckWorker
이 작업들은:
- 커서를 사용하여
main
데이터베이스의 두 소스 테이블을 스캔합니다. -
namespaces
및projects
의 항목을ci
데이터베이스의 타겟 테이블과 비교합니다. - 동기화되지 않은 항목을 Kibana 및 Prometheus에 보고합니다.
- 모든 불일치를 수정합니다.