부하 균등화 (Load Balancing)와 큐 이주 (Queue Migration)
핵심 인사이트 (3줄 요약)
- 본질: 멀티 코어(SMP) 환경의 부하 균등화(Load Balancing)는 운영체제 스케줄러가 여러 개의 CPU 코어 중 일거리가 넘쳐 터지기 직전인 코어(Overloaded)의 대기열(Run Queue)에서 프로세스를 쏙 빼내어, 놀고 있는 빈 코어(Idle)의 대기열로 이주(Migration)시켜 시스템 전체의 연산 효율을 극대화하는 메커니즘이다.
- 가치: 특정 코어만 100% 불타오르고 다른 코어는 0%로 놀고 있는 자원 비대칭(Asymmetry)의 바보 같은 상황을 막아, 사용자가 구매한 값비싼 64코어, 128코어 서버의 잠재력을 100% 끝까지 쥐어짜 내는 가장 기본적인 다중 처리 엔진이다.
- 융합: 그러나 프로세스를 딴 코어로 옮기면 기껏 데워놓은 L1 캐시가 박살 나는(Cache Miss) 치명적 딜레마(CPU Affinity의 반대 개념)가 발생하므로, 현대 리눅스의 스케줄링 도메인(Sched Domain)은 '캐시 공유 트리'와 'NUMA 노드 아키텍처'를 계산하여 가장 타격이 적은 가까운 코어로만 짐을 옮기는 고도의 융합 수학 모델로 진화했다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
-
개념:
- Run Queue (실행 대기열): 멀티 코어 OS는 중앙에 큐를 1개만 두면 락(Lock) 병목이 걸리므로, 코어 0번 전용 큐, 코어 1번 전용 큐처럼 코어마다 독립된 대기열을 갖는다.
- 부하 균등화 (Load Balancing): 주기적으로 각 코어 큐의 길이를 감시하다가, 불균형이 감지되면 바쁜 큐의 프로세스를 뽑아 널널한 큐로 강제로 이사(Migration) 시키는 작업.
-
필요성(문제의식):
- 코어가 4개(0,1,2,3번) 있다. 처음에 프로세스 4개가 하나씩 0,1,2,3에 예쁘게 분배되었다.
- 그런데 1, 2, 3번에 할당된 프로세스는 1초 만에 작업이 끝나 퇴근해 버렸고, 0번에 할당된 동영상 인코딩 프로세스만 10분째 혼자 돌아가며 무한히 스레드를 낳고 있다.
- 결국 1, 2, 3번 코어는 0%로 펑펑 놀고 있는데, 0번 코어의 큐에만 100개의 스레드가 쌓여서 사용자는 "컴퓨터가 멈췄다(렉 걸렸다)"고 분노하게 된다.
- 해결책: "선생님(OS)이 교실을 순찰하다가, 0번 분단 애들만 밀린 숙제가 100개고 나머지 분단은 놀고 있으면, 0번 애들의 숙제(스레드)를 뺏어서 노는 애들 책상에 강제로 던져줘라!"
-
💡 비유:
- 마트의 계산대(코어)가 4개 열려있다. 손님(프로세스)들이 눈치껏 각 줄(Run Queue)에 섰다.
- 그런데 1번 계산대 줄의 첫 손님이 하필 동전 천 개로 결제하느라 줄이 꽉 막혔다. 반면 2, 3, 4번 계산대는 손님이 다 빠져 점원이 핸드폰을 보고 있다.
- 부하 균등화(Migration): 마트 매니저(OS 스케줄러)가 나타나 "1번 줄 뒤에 서 계신 손님 5분! 비어있는 2번과 3번 계산대로 가세요!"라고 강제로 이동(이주)시켜서 전체 마트의 결제 속도를 정상화하는 탁월한 고객 관리술.
-
등장 배경:
- 전통적인 단일 프로세서(Uni-processor) 시대에는 큐가 하나라 필요 없는 개념이었으나, 1990년대 후반 SMP(Symmetric Multiprocessing) 구조가 표준화되고 각 코어별 런큐(Per-CPU Runqueue) 체제가 정착하면서 코어 간 눈치싸움을 조율하기 위한 필연적 알고리즘으로 탄생했다.
┌─────────────────────────────────────────────────────────────┐
│ Push Migration 과 Pull Migration 매커니즘 시각화 │
├─────────────────────────────────────────────────────────────┤
│ │
│ [ 상황: Core 0 큐 폭발, Core 1 큐 텅 빔 ] │
│ │
│ ┌── Core 0 Run Queue ──┐ ┌── Core 1 Run Queue ──┐ │
│ │ Proc A (실행 중) │ │ (텅 빔 - Idle) │ │
│ │ Proc B (대기 중) │ │ │ │
│ │ Proc C (대기 중) │ │ │ │
│ │ Proc D (대기 중) │ │ │ │
│ └──────────────────────┘ └──────────────────────┘ │
│ │
│ [ 1. Pull Migration (당겨오기) - 놀고 있는 놈이 훔쳐옴 ] │
│ - Core 1: "나 할 일 없네? 딴 코어 큐 좀 뒤져볼까?" │
│ - Core 1이 Core 0의 큐 락을 몰래 잡고 Proc C, D를 자버림! │
│ Proc C, D ─────────(가져옴)─────────▶ Core 1 큐 안착! │
│ │
│ [ 2. Push Migration (밀어내기) - OS 백그라운드 데몬의 개입 ] │
│ - 커널 스레드(Migration Thread): 주기적으로 전체 큐 모니터링 함. │
│ - 커널: "Core 0 불쌍하네. 내가 강제로 B, C 빼서 Core 1로 밀어줄게!"│
│ Proc B, C ─────────(밀어냄)─────────▶ Core 1 큐 안착! │
└─────────────────────────────────────────────────────────────┘
[다이어그램 해설] 리눅스 스케줄러(CFS)는 이 두 가지 톱니바퀴를 섞어 쓴다. Pull(당겨오기) 방식은 코어가 놀기 시작하는 그 찰나의 순간(Idle 진입)에 가장 능동적으로 딴 코어의 짐을 훔쳐 오는 즉각적 반응이다. 하지만 아무도 안 놀고 모두가 어설프게 바쁘면 아무도 짐을 훔쳐 가지 않아 불균형이 방치된다. 이를 막기 위해 Push(밀어내기) 방식이 도입되어, 감시자(Load Balancer)가 주기적(예: 매 밀리초마다)으로 깨어나 시스템 전체의 가중치를 무자비하게 평균치로 맞춰버린다. 이 상호보완적 구조 덕분에 128개의 코어를 가진 몬스터 서버도 단 1개의 코어조차 쉬지 않고 100% 혹사당하는 아름다운(?) 균형을 유지한다.
- 📢 섹션 요약 비유: 옆 부서는 일이 넘쳐 야근하는데 우리 부서는 놀고 있을 때, 우리 부서장이 양심의 가책을 느껴 스스로 일을 뺏어오는 착한 행동이 'Pull' 방식이고, 회사 사장님(백그라운드 스레드)이 헬기 타고 순찰하다가 "너네 놀지 말고 저쪽 일 강제로 가져와!"라고 지시를 때려버리는 것이 'Push' 방식의 강력한 통제입니다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
이주(Migration)의 치명적 독극물: 캐시 파괴(Cache Bouncing)
가장 무서운 진실은 "멀티 코어 시대에 부하 균등화는 만병통치약이 아니라, 엄청난 비용 청구서를 동반하는 악마의 거래"라는 점이다.
- 프로세스 A가 코어 0에서 돌면서 며칠 동안 계산한 따뜻한 데이터(Hot Cache)가 코어 0의 L1/L2 캐시에 꽉 차 있다.
- 스케줄러가 공평성을 맞추겠다고 프로세스 A를 코어 1로 이주(Migration)시켰다.
- 코어 1에서 깬 프로세스 A는 자기가 쓰던 변수를 달라고 요청한다. 코어 1의 L1 캐시에는 당연히 없다(Cache Miss).
- 코어 1은 코어 0의 L1 캐시를 무효화시키고 메인 메모리를 거쳐(수백 클럭 지연) 억지로 데이터를 끌어와야 한다. (캐시 무효화 및 MESI 프로토콜 병목 폭발).
해결책: 스케줄링 도메인 (Scheduling Domains) 아키텍처
리눅스는 캐시 파괴를 막기 위해 도메인(계급) 기반의 이주 정책을 만들었다. "아무 데나 던지는 게 아니라, 이왕 던질 거면 캐시를 공유하는 가장 가까운 형제 코어한테 던져라!"
┌───────────────────────────────────────────────────────────────────┐
│ CPU 캐시 지형도를 반영한 Sched Domains 마이그레이션 │
├───────────────────────────────────────────────────────────────────┤
│ │
│ [ NUMA Node 0 (물리 CPU 1번) ] [ NUMA Node 1 (물리 CPU 2번) ] │
│ ┌──────────────────────────┐ ┌──────────────────────────┐ │
│ │ L3 캐시 (공유) │ │ L3 캐시 (공유) │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┤ │ ┌──────┐ ┌──────┐ ┌──────┤ │
│ │ │L2캐시│ │L2캐시│ │L2캐시│ │ │L2캐시│ │L2캐시│ │L2캐시│ │
│ │ └─┬────┘ └─┬────┘ └─┬────┤ │ └─┬────┘ └─┬────┘ └─┬────┤ │
│ │ Core 0 Core 1 Core 2 │ │ Core 3 Core 4 Core 5 │ │
│ └──────────────────────────┘ └──────────────────────────┘ │
│ │
│ [ 리눅스 스케줄러의 타겟 탐색 논리 (Migration 우선순위) ] │
│ │
│ 1순위 🟢 [동일 L2 캐시 형제 (SMT/하이퍼스레딩)] │
│ : 물리 코어 안의 가상 논리 코어끼리 주고받음. 캐시 손실 0%. │
│ 2순위 🟡 [동일 L3 캐시 형제 (같은 Node 내)] │
│ : Core 0의 짐을 Core 1로 던짐. L1/L2는 날아가도 L3는 살아있음! │
│ 3순위 🔴 [완전 남남 (다른 NUMA Node)] │
│ : Core 0의 짐을 Core 3으로 던짐. 최악의 도박! 짐을 싸서 QPI 다리를│
│ 건너가야 하므로 성능 개박살. (진짜 0번이 죽기 직전일 때만 발동) │
└───────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 이것이 커널의 예술이다. 스케줄러는 부팅될 때 메인보드 하드웨어의 생김새(Topology)를 싹 다 스캔해서 족보(도메인)를 만든다. 부하가 터져서 이사(Migration)를 보내야 할 때, 스케줄러는 족보를 보고 "가장 촌수가 가까운 친척 코어"를 1순위로 찾는다. 같은 L3 캐시 지붕 아래 있는 코어끼리 짐을 넘기면, 프로세스는 L3 캐시에서 데이터를 쑥쑥 뽑아 쓰므로 성능 하락이 거의 없다. 하지만 다른 물리 칩(NUMA Node 1)으로 짐을 넘기는 행위는 이혼하고 다른 나라로 이민 가는 수준의 거대 오버헤드이므로, 임계치(Threshold)를 몹시 높게 잡아 웬만하면 실행되지 않게 꾹 참는다.
- 📢 섹션 요약 비유: 부하 균등화는 전학을 보내는 것과 같습니다. 반에 학생이 너무 많다고 무작정 서울 학생을 부산 학교(다른 NUMA 노드)로 전학 보내버리면 적응(캐시 미스)하느라 성적이 폭락합니다. 옆 반이나 기껏해야 옆 동네 학교(같은 L3 캐시)로 전학을 보내야 친구들(공유 데이터)도 만나고 성적도 유지할 수 있는 세심한 학군(도메인) 배정 로직입니다.
Ⅲ. 융합 비교 및 다각도 분석
CPU 친화성 (Affinity) vs 부하 균등화 (Load Balancing)의 전쟁
인프라 아키텍트의 머리를 가장 아프게 하는 모순이다. 두 기술은 서로 완벽히 정반대의 사상을 들이밀며 커널 안에서 싸우고 있다.
| 비교 항목 | 부하 균등화 (Load Balancing / Migration) | CPU 친화성 (CPU Affinity / Pinning) |
|---|---|---|
| 철학 | "놀고 있는 코어가 있으면 안 돼! 모두 다 평등하게 일해!" | "캐시 깨지는 게 제일 싫어. 난 썩어도 이 코어에서만 일할 거야!" |
| 운영체제 개입 | OS가 백그라운드에서 강제적, 지속적으로 개입함 (기본값). | 아키텍트가 강제로 수동 명시해야 발동함 (taskset). |
| 성능 최적화 타겟 | 전체 시스템의 총 스루풋 (Total Throughput) 펌핑 | 단일 VIP 프로세스의 초저지연 (Micro Latency) 방어 |
| 희생양 | 짐을 싼 프로세스의 캐시 히트율 파괴 (부분적 딜레이 발생) | 묶어둔 코어가 바빠지면 영원히 큐에서 대기 (기아 상태 위험) |
과목 융합 관점
-
쿠버네티스/클라우드 자원 관리 (Cgroups V2): 컨테이너 오케스트레이터는 이 커널의 눈치 싸움을 통제한다. CPU 1000m (1코어)를 할당하면(Request/Limit), 쿠버네티스는 기본적으로 OS의 '부하 균등화'에 이 컨테이너를 내던진다(이 코어 저 코어 옮겨 다님). 하지만 Guaranteed QoS 클래스를 주고 CPU 정책을
static으로 걸어버리면, 쿠버네티스는 OS의 멱살을 잡고 "얘는 이사(Migration) 대상에서 무조건 빼! Affinity 걸어 놔!"라고 강제하여 오케스트레이터가 커널의 밸런서를 짓밟는 상위 계층의 융합 통제를 보여준다. -
📢 섹션 요약 비유: 부하 균등화(공산주의)는 "모든 일꾼(코어)은 1초도 쉬지 않고 똑같이 일해야 한다"고 짐을 계속 섞는 방식이고, 친화성(장인정신)은 "장인은 한자리에서 자기 연장(캐시)만 써서 일해야 최고의 명품(초저지연)이 나온다"며 짐 섞기를 거부하는 철학입니다. 서버 설계자는 둘 중 어떤 종교를 택할지 결정해야 합니다.
Ⅳ. 실무 적용 및 기술사적 판단
실무 시나리오 및 서버 튜닝
-
시나리오 — 고부하 DB 서버의 Soft Lockup (CPU 100% 빙결 현상): 오라클/MySQL 전용 128코어 거대 NUMA 서버를 도입했다. 동접자가 몰리자 CPU 전체가 100%를 치면서 콘솔 접속조차 안 되는 딥 프리징(Soft Lockup)에 빠졌다.
perf를 돌려보니, 커널 스레드들이 자기들끼리 스핀락(Runqueue Lock)을 잡느라 미친 듯이 싸우고 있었다.- 원인 분석: 128개의 코어가 1밀리초마다 "누구 큐가 비었지? 짐 좀 뺏어올까?" 하고 서로 남의 큐(Runqueue) 문을 열어보려고 스핀락(Lock) 쟁탈전을 벌였다. 코어가 4개일 땐 괜찮았는데, 128개가 매 밀리초마다 서로의 큐 자물쇠를 돌려대니, 정작 DB 쿼리는 못 돌리고 **스케줄러의 부하 균등화 데몬 그 자체가 거대한 부하(Overhead)**가 되어 시스템을 목 졸라 죽인 것이다.
- 아키텍트 판단 (Migration 비용/주기 튜닝): 매니코어(Many-core) 시대에 OS 기본값 밸런싱은 쥐약이다. sysctl 커널 파라미터
kernel.sched_migration_cost_ns값을 디폴트 500µs에서 5000µs(5ms)로 10배 이상 올려버린다. 이 뜻은 "한 번 이 코어에 들어온 스레드는 캐시가 뜨거울 테니까 최소 5밀리초 동안은 다른 코어로 이사(Migration)시키지 마!"라는 방어막이다. 쓸데없는 짐 옮기기와 락 경합을 원천 억제하여 128코어가 온전히 DB 연산에만 몰빵하게 만드는 극단적 튜닝 기법이다.
-
시나리오 — Redis 같은 싱글 스레드 인메모리 처리의 널뛰기 지연: 앞선 내용의 반복이지만 가장 치명적인 함정이다. 코어 8개 서버에 Redis 프로세스 1개만 띄웠다. Redis는 싱글 스레드라 코어 1개만 쓴다. 그런데
top을 보면 0번 코어 100%, 그다음 초엔 3번 100%, 7번 100%... 코어가 널뛰기를 한다. 그리고 Redis 속도는 반토막이다.- 원인 분석: OS 스케줄러의 지나친 친절함이다. "어라? 0번 코어 혼자 일하네? 1,2,3번은 노네? 번갈아 가면서 일하게 해줄게!"라며 1초마다 Redis 프로세스를 이 코어 저 코어로 강제 이주(Migration) 시켰다. 이사 다닐 때마다 수백 메가바이트의 Redis 딕셔너리 캐시(L3/L2)가 몽땅 휴지통에 처박히고 재구축되며 처참한 속도 저하를 낳았다.
- 아키텍트 판단 (밸런서 무력화, Pinning 강제화): 로드 밸런서는 여러 개의 스레드가 있을 때 빛을 발한다. 싱글 스레드 거대 괴물 프로세스는 밸런서의 먹잇감이 되어서는 안 된다. 즉시
taskset이나systemd CPUAffinity로 Redis를 0번 코어에 시멘트로 발라버려야 한다(Pinning). OS 로드 밸런서의 개입을 원천 차단하는 것이 이 아키텍처의 정석이다.
┌───────────────────────────────────────────────────────────────────┐
│ 멀티코어/NUMA 환경의 CPU 스케줄러 아키텍트 결정 트리 │
├───────────────────────────────────────────────────────────────────┤
│ │
│ [ 64코어 이상의 거대 서버에 워크로드를 올린다 ] │
│ │ │
│ ▼ │
│ 이 서버가 Nginx 워커 100개, Node.js 100개처럼 쪼개진 앱을 돌리는가? │
│ ├─ 예 ─────▶ [ 부하 균등화(Load Balancing) 100% 맹신! ] │
│ │ (OS 커널의 기본 Migration 로직이 기가 막히게 분배해 줌)│
│ └─ 아니오 (단일 거대 DB나 초저지연 트레이딩 싱글스레드 앱이다) │
│ │ │
│ ▼ │
│ 앱의 메모리 용량이 너무 커서(수백 GB) 이사 갈 때 캐시 오염 타격이 심한가? │
│ ├─ 예 ─────▶ [ OS 로드 밸런서 개입을 강제 차단하라! ] │
│ │ - `isolcpus` 로 일반 스레드의 침범을 격리시키고, │
│ │ - `numactl`, `taskset`으로 특정 코어에 Affinity 고정│
│ └─ 아니오 ──▶ 일반 OS 정책 수용 │
└───────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 클라우드 엔지니어가 리눅스를 다룰 때 "기본값이 무조건 진리다"라는 환상에서 깨어나는 분기점이다. 리눅스 스케줄러(CFS)의 로드 밸런싱은 '일반적인' 데스크톱이나 짜잘한 웹 서버 수천 개를 돌릴 때 가장 훌륭한 범용 알고리즘일 뿐이다. 데이터의 덩치가 거대해지고 레이턴시가 나노초 단위로 내려가는 하이엔드 엔터프라이즈(DB, AI, 캐시) 생태계로 진입하면, 이 친절한 밸런서는 오지랖 넓고 서버를 박살 내는 악마(캐시 파괴자)로 돌변한다. 아키텍트는 하드웨어 캐시 구조를 꿰뚫고, OS의 목줄을 당겨 밸런서를 잠재울 줄 알아야 한다.
안티패턴
-
가상화(VM) 환경 위에서의 NUMA 인지 없는 무지성 로드 밸런싱: AWS나 VMware에서 거대 VM을 만들 때, 밑단 물리 서버가 여러 개의 NUMA 노드로 나뉘어 있다는 사실을 모른 채 vCPU만 무식하게 64개 펑펑 찍어내어 VM을 만든 경우. VM 내부의 OS 밸런서가 vCPU 0번에서 vCPU 60번으로 프로세스를 이주(Migration)시켰는데, 물리적으로는 이게 노드 0번과 노드 1번을 넘나드는 미친 왕복(Remote Access) 통신을 유발해 메모리 지연이 폭발한다. 클라우드 설계 시 vNUMA 토폴로지를 VM 내부에 통과시켜 주지 않으면, 이주(Migration) 알고리즘은 까막눈이 되어 서버의 명줄을 끊는다.
-
📢 섹션 요약 비유: 이삿짐센터(로드 밸런서)가 아파트 구조(NUMA)를 전혀 모른 채, 101호 방에서 놀고 있는 짐을 빈 곳이랍시고 100km 떨어진 부산지사 101호 방으로 옮겨버리는 대참사 안티패턴입니다. 짐을 옮길 때는 반드시 지형지물(도메인 족보)을 알고 옮겨야 합니다.
Ⅴ. 기대효과 및 결론
정량/정성 기대효과
| 구분 | Load Balancing 붕괴 시 (한쪽 몰림) | Sched Domain 기반 지능형 밸런싱 적용 시 | 개선 효과 |
|---|---|---|---|
| 정량 (전체 Throughput) | 특정 코어 100% 마비로 전체 TPS 떡락 | 코어 64개가 완벽히 99% 공평하게 분담 | 매니코어 서버의 잠재 연산력 100% 펌핑 (비용 회수) |
| 정량 (캐시 미스 페널티) | 무지성 이주로 인한 수백 µs 지연 빈발 | 동일 L3 캐시 내부 이주로 지연 10µs 이내 방어 | 이사(Migration)로 인한 성능 하락(Overhead) 90% 소멸 |
| 정성 (시스템 응답성) | 뒤에 줄 선 UI 프로세스 화면 먹통 (렉) | 노는 코어가 짐을 훔쳐가(Pull) 즉시 실행 | 사용자 체감 반응 속도(Responsiveness)의 극단적 쾌적함 보장 |
미래 전망
- 머신러닝 기반 밸런싱 (eBPF 스케줄러): 지금까지 커널의 짐 옮기기(Migration) 공식은 커널 소스 코드(C언어)에 빡빡하게 박혀(Hardcoded) 있었다. 미래의 리눅스(sched_ext 프레임워크)는 이 무거운 밸런서를 뜯어내고, 사용자가 직접 짠 eBPF 프로그램(또는 AI 모델)이 "지금 트래픽을 보니 이 스레드는 5초 뒤에 3번 코어로 옮기는 게 최적이다"라고 예측하여 런타임에 이주(Migration) 전략 자체를 실시간 패치하는 초지능형 스케줄러의 세계로 향하고 있다.
- 이기종(Heterogeneous) 코어 밸런싱: ARM의 big.LITTLE이나 인텔의 P-Core/E-Core 구조에서, 로드 밸런싱은 차원이 다른 난제를 맞았다. 이제는 빈 코어로 옮기는 게 문제가 아니라, 카카오톡 백그라운드는 약한 코어(E)로 던지고, 게임 스레드는 전기 먹는 하마 코어(P)로 즉시 이주시키는 '전력/성능 하이브리드' 마이그레이션이 모바일과 전기차(EV) 운영체제의 목숨줄을 쥔 핵심 알파 기술이 되었다.
참고 표준
- Linux CFS (Completely Fair Scheduler): SMP 시스템에서 Red-Black 트리를 기반으로 각 코어 큐의 가중치를 계산하고 밸런싱 데몬을 구동하는 현대 운영체제 스케줄링의 바이블 뼈대.
- ACPI SLIT (System Locality Information Table): 메인보드 펌웨어가 OS에게 "CPU 0번과 CPU 3번은 메모리 거리가 얼마나 멀다"는 거리 행렬(Distance Matrix)을 제공하여, OS가 이주(Migration) 시 도박판에 빠지지 않게 힌트를 주는 산업 하드웨어 표준.
부하 균등화(Load Balancing)와 큐 이주(Migration)는 컴퓨터 시스템이 수천 개의 톱니바퀴(프로세스)를 수십 개의 모터(코어)에 끊임없이 나눠 꽂으며 굴리는 장엄한 교향곡이다. 놀고 있는 자원을 절대 용납하지 않는 극단적인 공산주의적 자원 배분 철학 속에서, '캐시 파괴'라는 물리적 마찰을 견뎌내며 가장 최적의 타이밍에 짐을 훔쳐 오는 커널의 눈치 싸움이다. 당신이 수백 개의 브라우저 탭을 열고 유튜브를 틀어놔도 컴퓨터가 숨 막히지 않는 이유는, 지금 이 1초의 찰나에도 커널이 수만 번 남의 큐를 훔쳐보고 짐을 덜어주는 투명한 희생 덕분이다.
- 📢 섹션 요약 비유: 명절 고속도로에서 1차선이 꽉 막히면 차들이 알아서 빈 2차선, 3차선으로 차선을 변경하여(Migration) 결국 모든 차선이 꽉 찬 채로 똑같은 속도로 흘러가게 만드는 운전자들의 눈치 싸움(Load Balancing)이, CPU 코어 속에서도 나노초 단위로 치열하게 벌어지고 있는 것입니다.
📌 관련 개념 맵 (Knowledge Graph)
| 개념 명칭 | 관계 및 시너지 설명 |
|---|---|
| CPU 친화성 (Affinity) | "이사를 안 가고 한 코어에 뼈를 묻겠다"는 기술로, 이사를 무자비하게 강제하는 로드 밸런싱과 정확히 적대적인 대척점에 서 있는 쌍둥이 칼날이다. |
| NUMA (불균일 메모리 접근) | 이주(Migration) 시나리오에서 다른 노드로 스레드가 넘어갈 경우, 원격 메모리 폭탄을 맞아 성능이 박살 나게 만드는 가장 무서운 물리적 제약 지형이다. |
| Run Queue (대기열) | 각 코어마다 할당된 스레드 밥그릇으로, 코어들끼리 서로 남의 밥그릇을 훔쳐보며 남은 밥(스레드)을 당겨오는(Pull) 쟁탈전의 무대다. |
| 스핀락 (Spinlock) | 남의 Run Queue에서 스레드를 훔쳐(Migration) 오려면, 그 짧은 찰나에 남의 큐 자물쇠를 잠가야 하므로 스핀락 경합 병목이 필연적으로 발생한다. |
| Cache Miss (캐시 미스) | 부하 균등화라는 정의로운 명분이 실행된 직후, 프로세스가 낯선 코어에서 잠을 깰 때 맞이하는 차가운 데이터 부재의 가혹한 영수증이다. |
👶 어린이를 위한 3줄 비유 설명
- 4명의 마트 캐셔(코어)가 있는데, 1번 캐셔 앞에만 손님이 100명 줄 서 있고 나머지 3명은 폰을 보며 놀고 있어요.
- 1번 줄 맨 뒤의 손님은 속이 터지겠죠? 이때 마트 매니저(OS 스케줄러)가 나타나서 "기다리는 손님들! 저기 노는 2번, 3번 캐셔한테 가세요!"라고 줄을 옮겨줘요(이주/Migration).
- 덕분에 노는 캐셔 없이 모두가 열심히 일하게 되어 마트 손님들이 엄청 빨리 계산을 마치고 집에 갈 수 있게 된 거랍니다! (이게 부하 균등화예요)