작업 대기열 및 밸런싱
1) 작업 대기열이있는 이유
작업 대기열/작업 대기열은 시간과 속도별로 제조업체와 공연자를 분리합니다
스무디 피크: 전면 시스템과 무거운 서브 시스템 사이의 버퍼.
SLA 안정화: 로드 클래스의 우선 순위 및 격리.
결함 허용 오차를 단순화합니다: retrays, DLQ, 재 준비.
수평 저울: API를 변경하지 않고 작업자를 추가하십시
일반적인 영역: 결제 처리, 알림, 보고서/미디어 생성, ETL/ML 후 처리, 외부 API와의 통합.
2) 모델 및 기본 개념
생산자: 작업을 게시합니다 (페이로드 + 메타 데이터: dempotency 키, 우선 순위, 마감일).
큐/주제: 작업의 버퍼/로그.
작업자: 작업, 처리, 확인 (ack) 또는 오류가있는 반환.
가시성 시간 초과/임대: 자동 재배송 후 처리 기간 동안 "대여" 작업.
DLQ (Dead Letter Queue): 시도/치명적인 오류 제한 후 "매장" 작업.
한도/동시성: 근로자 당/대기열/임차인 소비 한도.
- 풀: 작업자 자신이 작업을 요청합니다 (부하 복용).
- 푸시: 브로커 보풀; 약한 근로자를 "채우는" 방지가 필요합니다.
3) 배달 및 확인 의미론
최대 한 번에: 배상금이 없습니다. 더 빠르지 만 가능한 손실.
최소 한 번 (대부분의 대기열에서 기본값): 중복이 가능합니다 → 처리기 demempotency가 필요합니다.
효과적으로 정확히 한 번: 응용 프로그램 수준 (demempotency, dedup, trations/outbox) 에서 달성되었습니다. 브로커는 도울 수 있지만 "마법의 총알" 은 도울 수 없습니다.
- Ack/Nack: 명확한 결과.
- 요청/재시도: 백오프 + 지터.
- 독 메시지-DLQ로 보내십시오.
4) 밸런싱 및 계획
4. 1 시퀀스 및 알고리즘
FIFO: 간단하고 예측 가능합니다.
우선 순위 큐: 우선 순위 클래스 (P0... P3).
WRR/WSR (가중 라운드 로빈/랜덤): 클래스간에 CPU 공유/전송.
WFQ/DRR (네트워크의 "공정한" 대기열과 유사): 임차인/클라이언트 당 공유.
마감일/EDF: 마감일이있는 작업.
공정한 점유율: "시끄러운 이웃" (임차인 당 할당량) 제한.
4. 2 처리 흐름
단일 비행/연결: 중복 주요 작업을 결합하십시오.
동시성 한도: 작업 유형/통합 (외부 API) 에 의한 병렬 처리에 대한 엄격한 제한.
4. 3 Geo and Shardening
키 (테넌트/id) → 데이터 지역별 파편, 파편 내 안정적인 순서.
끈적 끈적한 캐시/리소스: "첨부 된" 상태의 작업자에게 해시 라우팅.
5) Retrai, 백오프 및 DLQ
지수 백오프 + 지터: '베이스 2 ² 시도 λ랜덤'.
작업 당 최대 시도 및 총 마감일 (사용 시간).
오류 분류: 'retryable' (네트워크/제한), 'retryable' (검증/비즈니스 금지).
주차/지연 큐: 지연된 작업 (예: 15 분 후에 반복).
DLQ 정책: "유독 한" 메시지가 어디에서 어떤 조건에서 받는지 표시해야합니다. 리프로세서를 제공합니다.
6) 이념과 중복 제거
작업의 Idempotency-Key; 마지막 N 키에 대한 TTL이있는 저장 (Redis/DB):- 보기 → 건너 뛰기/병합/결과 캐시.
- 자연 키: 임의의 UUID 대신 'order _ id/payment _ id' 를 사용하십시오.
- 전송률-비즈니스 트랜잭션을 사용한 하나의 데이터베이스 트랜잭션에서 작업 사실과 상태를 기록하
- 정확히 한 번 파란색: 키에 의한 'UPSERT', 데이터베이스의 큐에서 "적어도 한 번", 데이터베이스에서 idempotency.
7) 멀티 테넌시 및 SLA 수업
클래스별로 별도의 대기열/스트림: '크리티컬', '표준', '벌크'.
임차인 당 쿼타 및 우선 순위 (골드/실버/브론즈).
격리: P0 하의 근로자 풀을 바칩니다. 배경-별도의 클러스터/노드에서.
입학 통제: 마감일에 처리 할 수있는 것 이상을 수락하지 마십시오.
8) 자동 검사 근로자
스케일링 메트릭: 대기열 깊이, 도착률, 처리 시간, SLA 마감일.
KEDA/수평 포드 오토 스케일러: SQS/Rabbit/Kafka 지연 깊이 트리거.
제한 요인: 외부 속도 제한 API, 데이터베이스 (백엔드를 파괴하지 마십시오).
9) 기술 옵션 및 패턴
9. 1 RabbitMQ/AMQP
교환: 직접/주제/팬 아웃; 대기열은 ack/ttl/DLQ (데드 레터 교환) 입니다.
Prefetch (QoS) 는 "작업자에게 몇 개의 작업이 있는지" 를 규제합니다.
ini x-dead-letter-exchange=dlx x-dead-letter-routing-key=jobs.failed x-message-ttl=60000
9. 2 SQS (및 아날로그)
가시성 시간 초과, DelaySecones, RedrivePolicy (DLQ).
Idempotence-응용 프로그램에서 (dedup table).
한계: 1-10 개의 게시물을 정육점; dempotent 타박상에 중점을 둡니다.
9. 3 카프카/NATS 제트 스트림
대규모 파이프 라인: 높은 처리량, 유지/재생.
로그 위의 작업 대기열: 하나의 작업 = 하나의 메시지; 키 제어를 통한/대상 파티셔닝 당 한 명의 작업자.
Retrai: 백오프가있는 개별 주제/주제 접미사.
9. 4 개의 Redis 대기열 (Sidekiq/Resque/Bull/Celery-Redis)
매우 낮은 대기 시간; 단일 비행을 위해 안정성 (RDB/AOF), 재 시도 키 및 잠금 키를 감시하십시오.
장기적인 억압이 아닌 "가벼운" 작업에 적합합니다.
9. 5 프레임 워크
셀러리 (파이썬), 사이드 키크 (루비), RQ/BullMQ (노드), Huey/Resque-기성품 배송, 일정, 미들웨어, 메트릭.
10) 라우팅 및 밸런싱 계획
Round-Robin: 작업의 "심각도" 를 고려하지는 않지만 고려하지 않습니다.
가중 RR: 작업자 용량/풀별 분포.
공정한/역압 인식: 작업자는 준비가되면 새로운 작업 만 수행합니다.
우선 순위 차선: 클래스 당 별도의 대기열; 가능한 경우 작업자는 [P0 →... → Pn] 순서대로 읽습니다.
해시 라우팅: '해시 (키)% 파편' -스테이트/캐시 처리 용.
11) 타임 아웃, 마감일 및 SLA
작업 시간 초과: 작업의 내부 "임대" (작업자 코드)
글로벌 마감일: T 시간 이후에는 작업이 의미가 없습니다-NACK → DLQ.
예산 인식: 마감일이 다가 오면 작업 (브라운 아웃) 을 줄입니다 (부분 결과).
12) 관찰 및 관리
12. 1 메트릭
'큐 _ 깊이', '도착 _ rate', 'service _ rate', 'lag' (Kafka), '보이지 않는 _ 메시지' (SQS).
'성공/실패/종료 _ total', '다시 시도', 'dlq _ in _ total', 'processing _ time _ ms {p50, p95, p99}'.
'deidempotency _ hit _ rate', 'dedup _ drops _ total', 'poison _ total'.
12. 2 개의 통나무/추적
상관 관계: 'job _ id', 'correlation _ id', 중복 키.
이벤트로 '재 시도/백오프/dlq' 를 표시하십시오. 초기 요청에서 연결합니다.
12. 대시 보드/알림 3 개
트리거: 깊이> X, p99> SLO, DLQ 성장, 고착 된 작업 (가시성이 만료> N), 핫 키.
13) 안전 및 준수
임차인 격리: 개별 대기열/키 공간, ACL, 할당량.
전송 및/또는 "휴식 중" 에 대한 암호화.
페이로드의 PII 최소화; 원유 PII 대신 해시/ID.
비밀: 작업 본문에 토큰을 넣지 말고 볼트/심판을 사용하십시오.
14) 반 패턴
dempotency가없는 Retrai → 복제 작업/돈 "두 번".
"모든 것을위한" 하나의 거대한 대기열 격리, 예측할 수없는 지연.
DLQ → 영원한 "유독 한" 작업이없는 끝없는 retrai.
가시성 시간 <처리 시간 → 계단식 복제본.
큐 → 네트워크/메모리 압력의 큰 페이로드; 객체 스토에 저장하고 링크를 전송하는 것이 좋습니다.
역압 → 작업자 질식없이 모델을 푸시하십시오.
한 명의 근로자 풀에서 중요한 작업과 대량 작업을 혼합합니다.
15) 구현 점검표
- SLA (P0/P1/P2) 및 볼륨에 의한 작업.
- 원하는 의미와 유지를 갖춘 브로커/프레임 워크를 선택하십시오.
- 디자인 키, 우선 순위 및 라우팅 (해시/파편/우선 순위 차선).
- 백오프 + 지터 리트레이 및 DLQ 정책 사용.
- 구현 demempotency (TTL이있는 키, upsert, 데드 스토어).
- 작업 당 가시성 및 일반 마감일 시간을 설정하십시오.
- 통합/테넌트 별 동시성 및 요율 제한.
- 퓨즈로 깊이/지연 자동 스케일링.
- 측정/추적/경고; "폭풍" 및 DLQ 오버플로에 대한 런북.
- 실패 테스트: 작업자의 몰락, "유독 한" 메시지, 과부하, 긴 작업.
16) 샘플 구성 및 코드
16. 1 셀러리 (Redis/Rabbit) -기본 흐름
python app = Celery("jobs", broker="amqp://...", backend="redis://...")
app.conf.task_acks_late = True # ack после выполнения app.conf.broker_transport_options = {"visibility_timeout": 3600}
app.conf.task_default_retry_delay = 5 app.conf.task_time_limit = 300 # hard timeout
@app.task(bind=True, autoretry_for=(Exception,), retry_backoff=True, retry_jitter=True, max_retries=6)
def process_order(self, order_id):
if seen(order_id): return "ok" # идемпотентность do_work(order_id)
mark_seen(order_id)
return "ok"
16. 2 RabbitMQ-DLQ/TTL
ini x-dead-letter-exchange=dlx x-dead-letter-routing-key=jobs.dlq x-message-ttl=600000 # 10 минут x-max-priority=10
16. 3 카프카-레벨 별 배상
orders -> orders.retry.5s -> orders.retry.1m -> orders.dlq
(스케줄러/크론 소비자를 통한 배송 지연으로 전송)
16. 4 NATS JetStream-소비자 백오프
bash nats consumer add JOBS WORKERS --filter "jobs.email" \
--deliver pull --ack explicit --max-deliver 6 \
--backoff "1s,5s,30s,2m,5m"
17) FAQ
Q: 푸시 대 풀을 언제 선택해야합니까?
A: 풀은 자연적인 역압과 "정직한" 균형을 제공합니다. 저속에서는 최소한의 TTFB가 필요하지만 리미터가 필요한 경우 푸시가 더 쉽습니다.
Q: 핫 키를 피하는 방법?
A: 복합 키 별 샤드 ('order _ id% N'), 버퍼 및 배치 프로세스는 키당 한계를 입력합니다.
Q: "정확히 한 번" 가능합니까?
A: 실제로-dempotence 및 트랜잭션 아웃 박스를 통해. 완전히 "수학적" 정확히 한 번은 거의 달성 할 수없고 비싸지 않습니다.
Q: 큰 작업 첨부 파일을 어디에 저장해야합니까?
A: 객체 스토리지 (S3/GCS) 및 작업-링크/ID; 브로커와 네트워크에 대한 압력을 줄입니다
Q: TTL/가시성을 선택하는 방법?
A: 가시성, p99 처리 시간 × 스톡 2-3 ×. TTL 작업-비즈니스 마감일이 줄어 듭니다.
18) 총계
강력한 큐잉 시스템은 전달 의미론, 우선 순위 및 제약 조건 사이의 균형입니다. 키 및 라우팅 설계, dempotency 보장, 백오프 및 DLQ로 다시 트레이, SLA 클래스에 리소스 할당 및 메트릭 모니터링. 그런 다음 배경 프로세스를 예측할 수 있고 안정적이며 확장 할 수 있습니다.