GitLab Cells 개발 가이드

GitLab Cells의 배경에 대해서는 디자인 문서를 참조하세요.

gitlab_main_cell 또는 gitlab_main_clusterwide 스키마 중 하나를 선택합니다.

사용 사례에 따라 기능이 셀 내 또는 클러스터 전역일 수 있으므로 해당 기능에 사용되는 테이블도 적절한 스키마를 사용해야 합니다.

테이블에 적절한 스키마를 선택할 때 다음 가이드라인을 고려하세요:

  • gitlab_main_cell을 기본으로 설정: 우리는 대부분의 테이블이 기본적으로 gitlab_main_cell 스키마에 할당될 것으로 예상합니다. 테이블의 데이터가 projects 또는 namespaces와 관련이 있는 경우 이 스키마를 선택하세요.
  • 테넌트 스케일 그룹과 상의: 특정 테이블에 gitlab_main_clusterwide 스키마가 더 적합하다고 생각하는 경우 테넌트 스케일 그룹의 승인을 얻으세요. 이것은 스케일링 영향을 미칠 수 있으며 스키마 선택을 재고해야 하기 때문에 중요합니다.

gitlab_main_clusterwide 스키마를 사용하는 테이블은 다른/모든 셀로 복제하기 위해 추가 작업이 필요합니다. 복제 전략은 각각의 경우에 따라 다를 것이지만 내부 API를 활용할 것입니다. 충돌을 방지하기 위해 응용프로그램도 수정되어 쓰기를 제한할 수 있습니다. 우리는 또한 팀에게 테이블을 필요에 따라 gitlab_main_clusterwide에서 gitlab_main_cell로 업데이트하도록 요청할 수 있으며, 이때 해당 테이블에 분할 키를 추가해야 할 수도 있습니다.

기존 테이블이 어떻게 분류되어 있는지 이해하려면 이 대시보드를 사용할 수 있습니다.

스키마가 할당된 후에는 병합 요청 파이프라인이 다음과 같은 이유 중 하나 이상으로 실패할 수 있으며, 이에 대한 가이드라인을 따르면 문제를 해결할 수 있습니다:

모든 셀-로컬 테이블에 대한 분할 키 정의

다음 gitlab_schema를 갖는 모든 테이블은 “셀-로컬”로 간주됩니다:

  • gitlab_main_cell
  • gitlab_ci
  • gitlab_sec

새로 생성된 셀-로컬 테이블은 해당 테이블의 db/docs/ 파일에 정의된 sharding_key를 가져야 합니다.

분할 키의 목적은 조직 격리 청사진에서 문서화되어 있지만, 간단히 말해서 이 열은 데이터베이스에서 특정 행을 소유하는 조직을 결정하는 표준 방식을 제공하는 데 사용됩니다. 나중을 위해 이 열은 데이터를 조직 경계를 넘지 않도록 제약 조건을 강제하는 데 사용될 것입니다. 또한 셀 간에 데이터 이관을 일관된 방식으로 제공하기 위해 사용될 것입니다.

외래 키의 실제 이름은 무엇이든지 상관없지만 projects 또는 groups의 행을 참조해야 합니다. 선택한 sharding_key 열은 null이 아니어야 합니다.

다중 sharding_key를 설정하여 nullable 열을 허용하는 것도 허용됩니다. 다만, 해당 테이블에 대해 적어도 하나의 키가 null이 아니어야 함을 올바르게 보장하는 체크 제약 조건이 있어야 합니다. 이러한 제약 조건을 생성하는 방법에 대한 지침은 다중 열에 대한 NOT NULL 제약 조건을 참조하세요.

다음은 유효한 분할 키의 예입니다:

  • 테이블 항목은 프로젝트에만 속함:

    sharding_key:
      project_id: projects
    
  • 테이블 항목은 프로젝트에 속하며, 외래 키는 target_project_id:

    sharding_key:
      target_project_id: projects
    
  • 테이블 항목은 네임스페이스/그룹에만 속함:

    sharding_key:
      namespace_id: namespaces
    
  • 테이블 항목은 네임스페이스/그룹에만 속하며, 외래 키는 group_id:

    sharding_key:
      group_id: namespaces
    
  • 테이블 항목은 네임스페이스 또는 프로젝트에 속함:

    sharding_key:
      project_id: projects
      namespace_id: namespaces
    

분할 키는 불변해야 합니다

분할 키 선택은 항상 불변해야 합니다. 따라서 기능에 따라 데이터를 이동할 수 있는 사용자 경험이 필요한 경우 새로운 행을 생성하도록 이동 기능을 재설계해야 할 수 있습니다. 이러한 사례의 예는 이슈 이동 기능에서 볼 수 있습니다. 이 기능은 실제로 기존 issues 행의 project_id 열을 변경하는 것이 아니라 새 issues 행을 생성하고 데이터베이스에서 원래 issues 행에 링크를 생성합니다. 조직 데이터를 이동할 수 있어야 하는 특히 어려운 기존 기능이 있는 경우 테넌트 스케일 팀에 연락하여 분할 키를 어떻게 관리할지에 대한 옵션들을 논의해야 할 것입니다.

프로젝트 및 네임스페이스에 대해 동일한 분할 키를 사용하기

개발자는 또한 테이블에서 사용되는 기능이 그룹 및 프로젝트 통합 청사진을 따르는 경우에는 테이블이 속할 수 있는 프로젝트에 대해 namespace_id만 사용할 수 있도록 선택할 수 있습니다. 이 경우 namespace_idProjectNamespace의 ID여야 하며 해당 네임스페이스가 속한 그룹의 ID는 아니어야 합니다.

organization_id를 분할 키로 사용하기

일반적으로 project_id 또는 namespace_id가 가장 일반적인 분할 키입니다. 그러나 테이블이 프로젝트 또는 네임스페이스에 속하지 않는 경우가 있습니다.

이러한 경우 organization_id는 분할 키의 옵션입니다. 다만, 아래 가이드라인을 따라야 합니다:

  • sharding_key 열은 여전히 불변해야 합니다.
  • 루트 레벨 모델에만 organization_id를 추가합니다(예: namespaces).
  • 이러한 테이블에는 그룹 또는 프로젝트와 관련된 데이터가 포함되어서는 안 됩니다(또는 그룹 또는 프로젝트에 속하는 레코드). 대신 project_id 또는 namespace_id를 사용하세요.
  • 많은 행을 포함하는 테이블은 좋은 후보가 아닙니다.
  • 이 테이블을 참조하는 다른 테이블이 있는 경우 참조 테이블 레코드가 다른 조직으로 이동해도 응용프로그램이 계속 작동해야 합니다.

만약 organization_id가 분할 키로서 최선의 선택이라고 생각한다면, 테넌트 스케일 그룹의 승인을 얻으세요. 이것은 데이터 이관에 대한 영향이 있을 수 있으며 분할 키 선택을 재고해야 할 수 있기 때문에 중요합니다.

예를 들어, 이 이슈는 기존 테이블에 organization_id를 분할 키로 추가했습니다.

desired_sharding_key 정의하여 sharding_key를 자동으로 다시 채우기

우리는 sharding_key가 없는 수백 개의 테이블에 sharding_key를 다시 채워넣어야 합니다. 이 프로세스는 새로운 열을 추가하고, 데이터를 관련 테이블에서 백업한 다음에 인덱스, 외래 키 및 비-널(Not-Null) 제약 조건을 추가하는 것과 같은 병합 요청을 만들어야 합니다.

개발자들의 반복적인 노력을 최소화하기 위해, 우리는이 특정 테이블에 대한 sharding_key를 다시 채울 방법을 간결하게 선언적으로 설명하는 방법을 도입했습니다. 이 내용은 나중에 필요한 모든 병합 요청을 자동으로 생성하는 데 사용될 것입니다.

desired_sharding_key의 예는 https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139336에 추가되었으며 다음과 같습니다:

--- # db/docs/security_findings.yml
table_name: security_findings
classes:
- Security::Finding

...

desired_sharding_key:
  project_id:
    references: projects
    backfill_via:
      parent:
        foreign_key: scanner_id
        table: vulnerability_scanners
        table_primary_key: id # 선택 사항. 기본값은 'id'
        sharding_key: project_id
        belongs_to: scanner

이 YAML 데이터가 어떻게 사용될지 가장 잘 이해하기 위해 수동으로 생성한 병합 요청에 GraphQL에서 매핑할 수 있습니다. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136800. 아이디어는 이것을 자동으로 생성하는 것입니다. YAML의 내용은 배치된 백그라운드 마이그레이션에서 sharding_key를 자동으로 채울 부모 테이블 및 그것의 sharding_key를 지정합니다. 또한 before_save에서 sharding_key를 자동으로 채울 모델에 추가될 belongs_to 관계도 지정합니다.

부모 테이블에 desired_sharding_key가 있는 경우 desired_sharding_key 정의

기본적으로 desired_sharding_key 구성은 선택한 sharding_key가 부모 테이블에 있는지 확인합니다. 그러나, 부모 테이블에도 desired_sharding_key 구성이 있고, 자체적으로 다시 채워넣기를 기다리고 있는 경우, awaiting_backfill_on_parent 필드를 포함해야 합니다. 예를 들어:

desired_sharding_key:
  project_id:
    references: projects
    backfill_via:
      parent:
        foreign_key: package_file_id
        table: packages_package_files
        table_primary_key: id # 선택 사항. 기본값은 'id'
        sharding_key: project_id
        belongs_to: package_file
    awaiting_backfill_on_parent: true

이러한 desired_sharding_key 구조가 sharding_key를 다시 채우기에 적합하지 않은 경우가 있을 수 있습니다. 이러한 경우에는 테이블을 보유하고 있는 팀이 필요한 병합 요청을 수동으로 추가해야 합니다.

특정 테이블에서 sharding 키를 제외하는 방법

특정 테이블은 다음과 같이 sharding 키에서 제외될 수 있습니다.

exempt_from_sharding: true

테이블의 데이터베이스 사전 파일에 위와 같이 추가할 수 있습니다. 이것은 다음과 같이 사용할 수 있습니다.

  • .com 데이터베이스에 데이터가 없기 때문에 JiHu 특정 테이블. !145905
  • operations_feature_flag_scopes와 같이 곧 삭제할 예정인 테이블. !147541
  • 각 셀에서 세포 작업을 지원하는 셀당 반드시 필요한 테이블, 셀당 고유 데이터가 있는 경우이지만 sharding 키가 정의될 수 없는 경우. 예를 들어, zoekt_nodes.

sharding 키 요구 사항에서 제외된 테이블은 또한 진행 대시보드에 나타나지 않습니다.

제외된 테이블은 데이터가 이동될 때 대상 셀의 데이터베이스에 외래 키 위반을 일으킬 수 있기 때문에 외래 키가 없거나 외래 키 참조가 느슨해서는 안 됩니다. 예 및 가능한 해결책에 대한 예제는 #471182을 참조하십시오.