데이터베이스 로드 밸런싱

Tier: Free, Premium, Ultimate Offering: Self-managed

데이터베이스 로드 밸런싱을 사용하면 읽기 전용 쿼리를 여러 PostgreSQL 노드에 분산하여 성능을 향상시킬 수 있습니다.

이 기능은 GitLab Rails 및 Sidekiq에서 기본 제공되며 외부 종속성 없이 데이터베이스 읽기 쿼리를 라운드로빈 방식으로 밸런스 조정할 수 있도록 구성할 수 있습니다:

데이터베이스 로드 밸런싱을 활성화하는 요구 사항

데이터베이스 로드 밸런싱을 활성화하려면 다음 사항을 확인하세요:

  • HA PostgreSQL 설정에 하나 이상의 세컨더리 노드가 프라이머리를 복제하고 있는지 확인합니다.
  • 각 PostgreSQL 노드가 동일한 자격 증명으로 동일한 포트에 연결되어 있는지 확인합니다.

Linux 패키지 설치의 경우, 다중 노드 설정을 구성할 때 각 PostgreSQL 노드에 PgBouncer가 구성되어 있어야 합니다.

데이터베이스 로드 밸런싱 구성

데이터베이스 로드 밸런싱은 다음 두 가지 방법 중 하나로 구성할 수 있습니다:

호스트

호스트 목록을 구성하려면 원하는 각 환경의 모든 GitLab Rails 및 Sidekiq 노드에서 다음 단계를 수행하세요:

  1. /etc/gitlab/gitlab.rb 파일을 편집합니다.
  2. gitlab_rails['db_load_balancing']에서 밸런스를 조정하려는 데이터베이스 호스트의 배열을 생성합니다. 예를 들어, primary.example.com, secondary1.example.com, secondary2.example.com 호스트에서 PostgreSQL을 실행하는 환경에서:

    gitlab_rails['db_load_balancing'] = { 'hosts' => ['primary.example.com', 'secondary1.example.com', 'secondary2.example.com'] }
    

    이러한 호스트는 gitlab_rails['db_port']로 구성된 동일한 포트에서 도달할 수 있어야 합니다.

  3. 파일을 저장하고 GitLab 다시 구성을 수행합니다.

참고: 프라이머리를 호스트 목록에 추가하는 것은 선택 사항이지만 권장됩니다. 이렇게 하면 프라이머리가 밸런스 조정된 읽기 쿼리를 처리할 수 있도록 성능이 향상되므로 프라이머리가 이러한 쿼리를 처리할 용량이 있는 시스템 성능이 향상됩니다. 매우 높은 트래픽을 요구하는 경우 프라이머리에 읽기 레플리카용 용량이 없을 수 있습니다. 프라이머리는 여부에 관계없이 쓰기 쿼리에 사용됩니다.

서비스 디스커버리

서비스 디스커버리를 통해 GitLab은 PostgreSQL 호스트 목록을 자동으로 검색하여 사용합니다. 주기적으로 DNS A 레코드를 확인하여 해당 레코드에서 반환된 IP를 이중 서버의 주소로 사용합니다. 서비스 디스커버리를 사용하려면 DNS 서버와 이중 서버의 IP 주소가 포함된 A 레코드만 있으면 됩니다.

Linux 패키지 설치 시 제공된 Consul 서비스는 DNS 서버로 작동하며 postgresql-ha.service.consul 레코드를 통해 PostgreSQL 주소를 반환합니다. 예를 들어:

  1. 각 GitLab Rails / Sidekiq 노드에서 /etc/gitlab/gitlab.rb를 편집하고 다음을 추가합니다.

    gitlab_rails['db_load_balancing'] = { 'discover' => {
        'nameserver' => 'localhost'
        'record' => 'postgresql-ha.service.consul'
        'record_type' => 'A'
        'port' => '8600'
        'interval' => '60'
        'disconnect_timeout' => '120'
      }
    }
    
  2. 파일을 저장하고 변경 사항이 적용되도록 GitLab을 다시 구성합니다.

옵션 설명 기본값
nameserver DNS 레코드 조회에 사용할 네임서버. localhost
record 조회할 레코드. 서비스 디스커버리 작동에 필요한 옵션입니다.  
record_type 조회할 레코드 유형. A 또는 SRV (GitLab 12.3 이상) 중 하나일 수 있습니다. A
port 네임서버의 포트. 8600
interval DNS 레코드를 확인하는 최소 시간(초). 60
disconnect_timeout 호스트 목록이 업데이트된 후 이전 연결을 종료하는데 걸리는 시간(초). 120
use_tcp UDP 대신 TCP를 사용하여 DNS 리소스 조회. false
max_replica_pools 각 Rails 프로세스가 연결하는 최대 복제본 수. 많은 수의 Postgres 복제본과 Rails 프로세스를 실행하는 경우 유용합니다. 기본 동작은 설정되지 않으면 무제한입니다. nil

record_typeSRV로 설정된 경우 GitLab은 계속해서 순환-로빈 알고리즘을 사용하고 레코드 내의 weightpriority를 무시합니다. SRV 레코드는 일반적으로 IP 대신 호스트명을 반환하므로 GitLab은 반환된 호스트명의 IP를 추가 섹션에서 찾아야 합니다. 호스트명에 대한 IP가 없으면 GitLab은 해당 호스트명의 A 또는 AAAA 레코드를 찾기 위해 구성된 네임서버에 대해 ANY 레코드를 요청해야 하며, IP를 해결할 수 없는 경우 해당 호스트명을 회전에서 제외해야 합니다.

interval 값은 확인 사이의 최소 시간을 지정합니다. 만약 A 레코드의 TTL이 이 값보다 크다면, 서비스 디스커버리는 해당 TTL을 준수합니다. 예를 들어, A 레코드의 TTL이 90초이면, 서비스 디스커버리는 다시 A 레코드를 확인하기 전에 적어도 90초를 기다립니다.

호스트 목록이 업데이트된 경우, 기존 연결이 종료되기까지 시간이 소요될 수 있습니다. disconnect_timeout 설정을 사용하여 이전 데이터베이스 연결이 종료되는 데 소요되는 시간 상한선을 정의할 수 있습니다.

구식 읽기 처리

  • GitLab Premium에서 GitLab Free로 14.0에서 이동되었습니다.

오래된 이중 서버에서 읽지 않도록 하기 위해 로드 밸런서는 주기적으로 해당 서버가 주 서버와 동기화되었는지 확인합니다. 데이터가 충분히 최근인 경우 이중 서버가 사용되고, 그렇지 않은 경우 무시됩니다. 이러한 확인의 부하를 줄이기 위해 특정 간격에서만 이러한 확인을 수행합니다.

이 동작에 영향을 주는 세 가지 설정 옵션이 있습니다.

옵션 설명 기본값
max_replication_difference 주 서버와 동기화되지 않은 이중 서버가 일정 기간 동안 데이터를 복제하지 않고 떨어질 수 있는 데이터 양(바이트). 8 MB
max_replication_lag_time 이중 서버가 사용을 중지하기 전에 주 서버와 일정 시간 뒤처지는 것을 허용하는 최대 시간(초). 60 초
replica_check_interval 이중 서버의 상태를 확인하기 전에 기다려야 하는 최소 시간(초). 60 초

대부분의 사용자에게 기본값이 충분합니다.

호스트 목록으로 이러한 옵션을 구성하려면 다음 예제를 사용하세요.

gitlab_rails['db_load_balancing'] = {
  'hosts' => ['primary.example.com', 'secondary1.example.com', 'secondary2.example.com'],
  'max_replication_difference' => 16777216, # 16 MB
  'max_replication_lag_time' => 30,
  'replica_check_interval' => 30
}

로깅

로드 밸런서는 database_load_balancing.log와 같은 여러 이벤트를 기록합니다.

  • 호스트가 오프라인으로 표시될 때
  • 호스트가 다시 온라인으로 표시될 때
  • 모든 보조가 오프라인일 때
  • 쿼리 충돌로 인해 다른 호스트에서 읽기가 다시 시도될 때

로그는 각 항목이 최소한 다음과 같은 JSON 객체 구조로 되어 있는 구조화되어 있습니다:

  • 필터링에 유용한 event 필드
  • 사람이 읽을 수 있는 message 필드
  • 이벤트별 메타데이터. 예를 들어, db_host
  • 항상 기록되는 컨텍스트 정보. 예를 들어, severitytime

예시:

{"severity":"INFO","time":"2019-09-02T12:12:01.728Z","correlation_id":"abcdefg","event":"host_online","message":"Host came back online","db_host":"111.222.333.444","db_port":null,"tag":"rails.database_load_balancing","environment":"production","hostname":"web-example-1","fqdn":"gitlab.example.com","path":null,"params":null}

구현 세부 정보

쿼리 균형

읽기 전용 SELECT 쿼리는 주어진 모든 호스트 사이에서 균형을 유지합니다. 트랜잭션을 포함한 그 밖의 모든 것은 주 서버에서 실행됩니다. 예를 들어, SELECT ... FOR UPDATE 와 같은 쿼리도 주 서버에서 실행됩니다.

준비된 문

준비된 문은 로드 밸런싱과 잘 작동하지 않으며, 로드 밸런싱이 활성화된 경우 자동으로 비활성화됩니다. 이는 응답 시간에 영향을 미치지 않아야 합니다.

주 서버 고정

쓰기가 수행된 후, GitLab은 일정 시간 동안(쓰기를 수행한 사용자의 범위 내에서) 주 서버를 사용하여 작업을 수행합니다. 보조가 따라잡은 경우 또는 30초 후에 GitLab은 보조를 사용하도록 되돌아갑니다.

장애 조치

장애 조치나 응답이 없는 데이터베이스의 경우, 로드 밸런서는 다음 사용 가능한 호스트를 사용하려고 시도합니다. 보조가 없는 경우 작업은 대신 주 서버에서 수행됩니다.

데이터를 쓰는 동안 연결 오류가 발생하면, 작업은 지수적인 백오프를 사용하여 최대 3회 다시 시도합니다.

로드 밸런싱을 사용하는 경우, 데이터베이스 서버를 안전하게 다시 시작하여 바로 사용자에게 오류가 표시되지 않아야 합니다.

개발 가이드

데이터베이스 로드 밸런싱에 대한 자세한 개발 가이드는 개발 문서를 참조하세요.