데이터베이스 로드 밸런싱
- GitLab Premium 9.0에서 소개됨.
- 14.0에서 GitLab Premium에서 GitLab 무료로 이동됨.
- GitLab 14.1에서 Sidekiq에 도입됨.
데이터베이스 로드 밸런싱을 통해 읽기 전용 쿼리를 여러 PostgreSQL 노드에 분산하여 성능을 향상시킬 수 있습니다.
이 기능은 GitLab Rails 및 Sidekiq에서 기본적으로 제공되며, 외부 의존성 없이 데이터베이스 읽기 쿼리를 라운드로빈 방식으로 분산할 수 있도록 구성할 수 있습니다.
데이터베이스 로드 밸런싱을 활성화하기 위한 요구 사항
데이터베이스 로드 밸런싱을 활성화하려면 다음 사항을 확인하세요:
- HA PostgreSQL 설정에 하나 이상의 보조 노드가 기본 노드를 복제하고 있는지 확인합니다.
- 각 PostgreSQL 노드가 동일한 자격 증명으로 동일한 포트에 연결되어 있는지 확인합니다.
Linux 패키지 설치의 경우, 다중 노드 설정을 구성할 때 각 PostgreSQL 노드에서 PgBouncer가 구성되어 있어야 합니다.
데이터베이스 로드 밸런싱 구성
데이터베이스 로드 밸런싱은 다음 두 가지 방법 중 하나로 구성할 수 있습니다:
호스트
호스트 디렉터리을 구성하려면 각 환경에 대해 모든 GitLab Rails 및 Sidekiq 노드에서 다음 단계를 수행하세요:
-
/etc/gitlab/gitlab.rb
파일을 편집합니다. -
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']
로 구성된 동일한 포트에서 접근 가능해야 합니다. - 파일을 저장하고 GitLab 재구성을 수행합니다.
서비스 디스커버리
- GitLab 11.0에서 도입됨.
서비스 디스커버리를 사용하면 GitLab은 사용할 PostgreSQL 호스트 디렉터리을 자동으로 검색할 수 있습니다. 주기적으로
A
레코드를 확인하여 이 레코드에서 반환된 IP를 두 번째 노드의 주소로 사용합니다. 서비스 디스커버리를 사용하려면 DNS 서버와 A
레코드를 포함하는 IP 주소가 필요합니다.
Linux 패키지 설치를 사용하는 경우, 제공된 Consul 서비스가 DNS 서버로 작동하고 postgresql-ha.service.consul
레코드를 통해 PostgreSQL 주소를 반환합니다.
예를 들어 다음과 같이 각 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'
}
}
파일을 저장하고 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 프로세스를 실행하는 경우 이 제한이 유용합니다. 제한이 없는 경우 모든 Rails 프로세스가 기본적으로 모든 레플리카에 연결됩니다. | nil |
record_type
이 SRV
로 설정된 경우 GitLab은 라운드로빈 알고리즘을 계속 사용하고 레코드의 weight
및 priority
를 무시합니다.
interval
값은 확인 사이에 더 큰 TTL이있는 경우 해당 TTL을 존중합니다. 예를 들어, A
레코드의 TTL이 90초 이상이면
서비스 디스커버리는 A
레코드를 다시 확인하기 전에 적어도 90초 기다립니다.
호스트 디렉터리이 업데이트되면 이전 연결이 종료되는데 시간이 걸릴 수 있습니다.
disconnect_timeout
설정을 사용하여 이전 데이터베이스 연결을 종료하는 데 소요되는 시간 상한을 강제로 할 수 있습니다.
스테일 리드 처리
- GitLab Premium의 14.0에서 GitLab Free로 이동했습니다.
오래된 보조 데이터베이스에서 읽는 것을 방지하기 위해 로드 밸런서는 주 데이터베이스와 동기화되었는지 확인합니다. 데이터가 충분히 최신이라면 보조 데이터베이스를 사용하고, 그렇지 않으면 무시합니다. 이러한 확인의 오버헤드를 줄이기 위해 우리는 일정한 간격으로만 이를 수행합니다.
이러한 동작에 영향을 미치는 3가지 구성 옵션이 있습니다.
옵션 | 설명 | 기본값 |
---|---|---|
max_replication_difference
| 보조가 데이터를 복제하지 않은 기간이 얼마나 지체될 수 있는지에 따른 바이트로 된 데이터 양. | 8MB |
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, # 16MB
'max_replication_lag_time' => 30,
'replica_check_interval' => 30
}
로깅
로드 밸런서는 다음과 같은 여러 이벤트를 database_load_balancing.log
에 로깅합니다.
- 호스트가 오프라인으로 표시된 경우
- 호스트가 다시 온라인으로 표시된 경우
- 모든 보조 호스트가 오프라인인 경우
- 쿼리 충돌로 인해 읽기가 다른 호스트에서 다시 시도되는 경우
로그는 각 항목이 적어도 다음을 포함하는 JSON 객체로 구성됩니다 :
- 필터링에 유용한
event
필드 - 읽기 가능한
message
필드 - 특정 이벤트에 고유한 메타데이터. 예를 들어
db_host
- 항상 로깅되는 맥락 정보. 예를 들어
severity
및time
예를 들면:
{"severity":"INFO","time":"2019-09-02T12:12:01.728Z","correlation_id":"abcdefg","event":"host_online","message":"호스트가 다시 온라인으로 표시됨","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회까지 재시도됩니다.
로드 밸런싱을 사용할 때, 데이터베이스 서버를 재시작해도 사용자에게 오류가 즉시 표시되지 않아야 합니다.
개발 가이드
데이터베이스 로드 밸런싱에 대한 자세한 개발 가이드는 개발 문서를 참조하세요.