핵심 인사이트 (3줄 요약)
- 과거 하드디스크(HDD)를 위해 설계된 SATA(AHCI) 인터페이스는 **단 1개의 큐(대기열)**만 가지고 있었으며, 여기에 최대 32개의 명령어만 세워둘 수 있었다. 코어가 64개라도 입구가 1개뿐이라 심각한 병목이 일어났다.
- 플래시 메모리(SSD)를 위해 처음부터 백지에서 설계된 **NVMe (Non-Volatile Memory Express)**의 핵심은, 무려 **65,535개의 큐 쌍(Queue Pairs)**을 지원한다는 점이다.
- CPU의 코어마다 자신만의 독점적인 큐(전용 입구)를 1개씩 할당해 주어, 코어들끼리 락(Lock)을 걸고 싸우지 않고 SSD에 동시에 데이터를 때려 넣을 수 있는 무한대의 병렬성을 제공한다.
Ⅰ. 단일 큐의 비극: 톨게이트 병목 현상
초고속 SATA SSD를 샀는데도 왜 서버 성능이 안 올랐을까요? AHCI 규격은 명령어 대기열(Queue)이 딱 1개(깊이 32개)였습니다.
서버에 CPU 코어가 64개 있습니다. 코어들이 각자 SSD에 데이터를 쓰려고 우르르 달려갑니다.
- 코어 1번이 큐에 명령어를 넣는 동안, 2번부터 64번 코어는 락(Lock)이 걸려 뒤에서 멀뚱멀뚱 기다려야 합니다.
- 큐 사이즈도 32개라, 한 번에 주문을 32개밖에 못 받습니다.
📢 섹션 요약 비유: 64차선 고속도로(CPU)를 뚫어놨는데, 톨게이트(AHCI Queue) 직원이 1명뿐이고 하이패스도 없습니다. 차들이 아무리 빨리 달려와도 톨게이트에서 64대가 1줄로 서서 순서를 기다려야 합니다.
Ⅱ. NVMe 큐 쌍 (Queue Pairs)의 혁명
NVMe는 톨게이트를 무한대로 늘렸습니다. **큐 쌍 (Queue Pair = Submission Queue + Completion Queue)**을 무려 65,535세트나 만들 수 있게 설계했습니다. 각 큐에는 명령어를 65,535개나 세워둘 수 있습니다. ($65,535 \times 65,535$ 병렬성)
어떻게 락(Lock)을 없앴는가?
- 64코어 CPU가 부팅될 때, 운영체제(NVMe 드라이버)는 "코어 1개당 무조건 자기 전용 큐 쌍을 1개씩(1:1 매핑)" 할당해 줍니다.
- 코어 1번은 자기가 데이터를 쓸 때 1번 큐(자기 전용 문)에 그냥 데이터를 집어 던집니다. 남의 눈치를 볼 필요가 없으므로 락(Lock) 연산이 0입니다.
- 코어 64번도 동시에 자기 전용 64번 큐에 데이터를 던집니다.
- NVMe SSD 컨트롤러(하드웨어 칩) 내부의 여러 스레드가 이 64개의 큐에서 동시에 데이터를 쑥쑥 뽑아가서 플래시 메모리에 미친 듯이 병렬로 써버립니다.
큐 병렬화 구조 (ASCII 다이어그램)
[ 과거: AHCI (SATA) ] [ 현대: NVMe 큐 쌍 ]
코어1 코어2 코어3 ... 코어64 코어1 코어2 코어3 ... 코어64
│ │ │ │ │ │ │ │
└──┬──┴──────┴────────┘ ▼ ▼ ▼ ▼
▼ (Lock 병목) [큐 1번] [큐 2번] [큐 3번] [큐 64번]
[ 단일 큐 (32칸) ] (코어끼리 간섭 0%, 동시에 쏟아짐)
▼ └────┬───┴───┬────┘
SATA SSD ▼ ▼
초고속 NVMe SSD 컨트롤러
📢 섹션 요약 비유: 톨게이트(Queue)를 6만 5천 개 지었습니다. 그리고 1번 차선은 1번 톨게이트만, 64번 차선은 64번 톨게이트만 쓰도록 완벽히 분리했습니다. 차선 변경(Lock)이 없으니 차가 막힐 일이 아예 물리적으로 사라졌습니다.
Ⅲ. NVMe의 성능을 100% 뽑아내는 폴링(Polling)
NVMe는 큐가 너무 많고 처리가 빛의 속도라, 디스크가 처리를 다 끝낼 때마다 CPU에 인터럽트(완료됐다고 초인종 누름)를 걸면 CPU가 마비됩니다. 그래서 앞 장에서 배운 SPDK (Storage Performance Development Kit) 같은 기술을 적용하여, 인터럽트를 끄고 CPU가 자기가 던져놓은 큐의 도착함(Completion Queue)을 눈으로 빤히 쳐다보고(Polling) 있다가 낚아채는 방식으로 궁극의 영점 지연(Zero Latency) 아키텍처를 완성합니다.