TimescaleDB 백그라운드 워커와 작업 이해하기
Source: Dev.to
번역할 텍스트가 제공되지 않았습니다. 번역을 원하는 본문을 알려주시면 한국어로 번역해 드리겠습니다.
백그라운드 워커의 메커니즘
add_compression_policy(), add_retention_policy(), add_continuous_aggregate_policy()를 호출할 때마다 TimescaleDB는 예약 작업을 등록합니다. 각 작업은 PostgreSQL 백그라운드 워커에서 실행되며, 이는 클라이언트 연결과는 별도로 독립적으로 동작하는 프로세스입니다.
사용 가능한 백그라운드 워커 수는 두 가지 설정으로 제어됩니다:
| 설정 | 설명 | 기본값 |
|---|---|---|
timescaledb.max_background_workers | TimescaleDB 자체 스케줄러에 대한 상한선 | 8‑16 |
max_worker_processes | 모든 확장, 병렬 쿼리 및 논리 복제에서 공유되는 PostgreSQL 전역 제한 | — |
현재 설정을 확인하려면 다음을 실행하십시오:
SELECT name, setting, unit
FROM pg_settings
WHERE name IN (
'timescaledb.max_background_workers',
'max_worker_processes',
'max_parallel_workers'
)
ORDER BY name;
활성화된 모든 작업을 나열하려면 다음을 실행하십시오:
SELECT
job_id,
proc_name,
hypertable_name,
schedule_interval,
scheduled AS is_active
FROM timescaledb_information.jobs
WHERE scheduled = true
ORDER BY proc_name, hypertable_name;
소진이 발생하는 방식
수식은 간단하지만 가차가 없습니다.
- 압축, 보존 기간, 그리고 연속 집계가 적용된 각 하이퍼테이블은 세 개의 작업을 생성합니다.
- 하이퍼테이블 8개 → 작업 24개.
- TimescaleDB의 내부 유지 관리 작업을 추가하면, 예약된 작업이 100개가 훨씬 넘을 수 있습니다.
기본값인 max_background_workers 16은 이러한 부하를 위해 설계된 것이 아닙니다.
작업이 워커를 할당받지 못하면 오류를 발생시키지 않습니다. 단순히 스케줄러 큐에서 대기합니다. 스케줄 간격 내에 자유 워커가 열리지 않으면, 다음 호출이 현재 호출 뒤에 쌓입니다. 몇 시간 동안 백로그가 형성되고 각 사이클마다 누적됩니다.
최악의 경우: 작업 실행 시간이 스케줄 간격을 초과합니다.
15분이 걸리는 압축 작업이 10분마다 스케줄되면 워커 슬롯을 영구적으로 차지하게 되어 절대 따라잡을 수 없습니다. 각 사이클마다 또 다른 대기 호출이 추가되어 다른 작업 유형이 워커를 얻지 못하게 합니다.
문제 진단
작업 수와 워커 제한 비교
WITH worker_config AS (
SELECT current_setting('timescaledb.max_background_workers')::int AS max_workers
),
active_jobs AS (
SELECT count(*) AS total_scheduled_jobs
FROM timescaledb_information.jobs
WHERE scheduled = true
)
SELECT
wc.max_workers,
aj.total_scheduled_jobs,
CASE
WHEN aj.total_scheduled_jobs = 0 THEN 'FAILING'
WHEN js.total_runs = 0 THEN 'NEVER RUN -- likely queued'
ELSE 'OK'
END AS health_status
FROM timescaledb_information.jobs j
JOIN timescaledb_information.job_stats js ON j.job_id = js.job_id
ORDER BY js.total_failures DESC, j.proc_name;
주요 경고 신호
total_runs = 0– 작업이 등록되었지만 워커를 획득하지 못함(순수 큐 기아).consecutive_failures증가 – 워커는 획득했지만 작업이 실패함(잠금 경쟁이나 압축 중 OOM 등).last_run_duration>schedule_interval– 다음 호출 전에 작업을 끝낼 수 없어 워커 슬롯을 영구적으로 차단함.
워커 풀 적정 규모 맞추기
공식은 간단합니다:
total_policies + 2 (internal jobs) = minimum max_background_workers
정확한 권장값을 계산하려면:
WITH policy_count AS (
SELECT count(*) AS total_jobs
FROM timescaledb_information.jobs
WHERE scheduled = true
)
SELECT
total_jobs,
total_jobs + 2 AS recommended_workers,
'ALTER SYSTEM SET timescaledb.max_background_workers = '
|| (total_jobs + 2) AS sql_to_run
FROM policy_count;
변경을 적용합니다:
ALTER SYSTEM SET timescaledb.max_background_workers = 28;
ALTER SYSTEM SET max_worker_processes = 32;
-- 전체 PostgreSQL 재시작이 필요합니다 – pg_reload_conf()만으로는 충분하지 않음
과다 프로비저닝은 비용이 거의 들지 않습니다. 유휴 백그라운드 워커 하나당 약 5‑10 MB의 메모리와 CPU는 전혀 사용되지 않습니다. max_background_workers를 32 또는 64로 설정해도 20개의 작업을 실행 중인 서버에서는 측정 가능한 성능 저하가 없습니다. 반면, 부족한 프로비저닝은 자동화 파이프라인 전체를 조용히 깨뜨립니다.
PostgreSQL 18 + TimescaleDB 2.24에 대한 참고
PostgreSQL 18과 TimescaleDB 2.24를 실행 중이라면, add_job()을 통해 등록된 사용자 정의 함수가 “cache lookup failed for function” 오류와 함께 실패한다는 점에 유의하십시오. 이 버전 조합의 백그라운드 워커는 public‑schema 함수들을 해결할 수 없습니다. 해결 방법은 사용자 정의 스케줄 작업에 시스템 cron을 사용하고, TimescaleDB는 내장 정책(압축, 보존, 집계 새로 고침)을 정상적으로 처리하도록 하는 것입니다.
예방 체크리스트
-
새 하이퍼테이블을 만들 때마다 작업 수를 세세요.
전체 정책이 적용된 각 하이퍼테이블은 3개의 작업을 추가합니다. 작업자 설정을 사전에 업데이트하세요. -
total_failures와consecutive_failures를 정기적으로 모니터링하세요.
timescaledb_information.job_stats를 주간으로 조회하거나 자동 모니터링을 설정하세요. -
작업 지속 시간이 스케줄 간격보다 짧은지 확인하세요.
last_run_duration이schedule_interval에 근접하면 다음을 고려하세요:- 간격을 늘리기,
- 청크 크기를 줄이기, 또는
- 작업자를 추가하기.
-
max_worker_processes를max_background_workers보다 높게 설정하세요.
병렬 쿼리와 논리 복제를 위한 여유를 남겨두세요. -
주의: 두 설정 모두 PostgreSQL 전체 재시작이 필요합니다.
유지 보수 창에 변경을 계획하세요. -
작업자 크기 설정을 하이퍼테이블 설정의 일부로 간주하세요.
정책을 추가 → 작업자를 추가합니다. 절대 사후 고려 사항으로 여기지 마세요.
백그라운드 작업자 고갈은 완전히 예방할 수 있습니다. 해결 방법은 SQL 문 하나와 재시작뿐입니다. 어려운 부분은 자동화가 조용히 멈추기 전에 이를 찾아야 한다는 것을 아는 것입니다.