12강 / 20강
저장장치 — IOPS가 곧 주문 처리량이다
HDD와 SSD · 순차와 랜덤 · 지연시간과 큐
쇼핑몰에서 주문이 하나 들어오면 디스크에 몇 번 쓸까요?
- 주문 행 하나 INSERT
- 주문 상품 3줄 INSERT
- 재고 3줄 UPDATE
- 트랜잭션 로그(WAL) 기록 + fsync
- 액세스 로그 한 줄
디스크가 초당 몇 건을 감당하느냐가 곧 초당 몇 건의 주문을 받을 수 있느냐입니다. 그 숫자를 IOPS라고 불러요.
HDD와 SSD — 근본적으로 다른 기계
| HDD 7200rpm | SATA SSD | NVMe SSD | |
|---|---|---|---|
| 랜덤 읽기 지연 | ~8 ms | ~0.18 ms | ~0.09 ms |
| 랜덤 IOPS | ~120 | ~95,000 | ~580,000 |
| 순차 읽기 | ~200 MB/s | ~540 MB/s | ~6,500 MB/s |
| 1GB당 가격 | 가장 쌈 | 중간 | 비쌈 |
순차 속도는 3~30배 차이인데 랜덤 IOPS는 5000배 차이입니다. DB는 거의 전부 랜덤 접근이라서, 이 차이가 그대로 쇼핑몰 속도가 됩니다.
디스크 지연이 곧 주문 처리 한계입니다.
Python
브라우저에서 실행
순차와 랜덤 — 블록 크기가 만드는 차이
같은 1GB를 옮겨도 4KB씩 25만 번과 1MB씩 1000번은 완전히 다릅니다. 작게 쪼갤수록 요청 하나하나의 오버헤드가 붙거든요.
같은 512MB인데 블록 크기만 다릅니다.
bash
브라우저에서 실행
차이가 크죠. 그래서 백업 스크립트에서 bs=1M 을 주는 것만으로
백업 시간이 몇 배 줄어들 때가 있습니다.
순차 6500MB/s인 장치가 랜덤에서는 몇 MB/s인지 보세요.
bash
브라우저에서 실행
%util 90% 이상 + await 증가 = 디스크 병목입니다.
bash
브라우저에서 실행
iostat -x 읽는 법
| 칸 | 뜻 | 언제 걱정하나 |
|---|---|---|
r/s w/s | 초당 읽기/쓰기 횟수 = IOPS | 장치 한계에 가까울 때 |
rkB/s wkB/s | 초당 바이트 = 대역폭 | 순차 작업이 많을 때 |
r_await w_await | 요청 하나가 기다린 평균 시간(ms) | SSD에서 10ms 넘으면 이상 |
aqu-sz | 평균 큐 길이 | 계속 크면 줄이 밀리는 중 |
%util | 장치가 바빴던 시간 비율 | 90% 이상이면 포화 의심 |
주의: NVMe는 병렬 처리를 하기 때문에 %util 100%가 꼭 포화를 뜻하지 않습니다.
await가 함께 올라가는지를 같이 봐야 해요.
SSD에는 [none] 스케줄러가 맞습니다 — 줄 세울 필요가 없거든요.
bash
브라우저에서 실행
🤔 확인 문제
쇼핑몰 DB 서버를 HDD에서 NVMe SSD로 바꿨더니 순차 백업 속도는 3배 빨라졌는데 주문 처리량은 50배 빨라졌습니다. 왜일까요?
해설 HDD의 랜덤 지연은 바늘이 움직이는 물리 시간(~8ms)이라 줄일 수가 없습니다. 순차는 200 → 6500MB/s(30배)지만, 랜덤 IOPS는 120 → 580,000(약 5000배)이에요. DB 성능은 랜덤 IOPS가 결정합니다.
🤔 확인 문제
iostat -x에서 %util 99%, await 0.3ms, aqu-sz 0.05 가 나왔습니다. 디스크가 병목일까요?해설 %util은 '장치에 요청이 하나라도 있던 시간의 비율'입니다. NVMe는 수천 개를 동시에 처리하니 요청이 끊이지 않으면 100%가 나와요. 진짜 신호는 await(기다린 시간)와 aqu-sz(줄 길이)입니다. 여기선 둘 다 여유롭네요.