💿 Storage

I/O 스케줄러

개요

I/O 스케줄러는 블록 레이어에서 I/O 요청의 순서와 전달을 관리하여 디스크 성능과 지연시간을 최적화하는 커널 컴포넌트이다. 과거에는 단일 큐 기반의 CFQ(Complete Fair Queueing)가 주류였으나, NVMe SSD의 등장과 멀티코어 시스템의 확산으로 블록 레이어가 재설계되면서 blk-mq(Multi-Queue Block IO Queueing Mechanism) 아키텍처로 전환되었다. 현재 리눅스 커널에서 사용 가능한 주요 I/O 스케줄러는 mq-deadline, BFQ, Kyber, 그리고 스케줄러 없이 직접 전달하는 none 네 가지이다.

현대 I/O 스케줄러는 하드 디스크의 헤드 이동 비용을 줄이는 것뿐 아니라, SSD의 병렬 처리 능력 활용, cgroup 기반 대역폭 제어, 지연시간 목표 유지 등 다양한 목표를 동시에 추구한다. 각 스케줄러는 특정 워크로드와 장치 유형에 최적화되어 있으므로, 시스템의 사용 목적에 맞는 선택이 중요하다.

핵심 개념

I/O 스케줄러 아키텍처

blk-mq 아키텍처

blk-mq는 소프트웨어 스테이징 큐(software staging queue)와 하드웨어 디스패치 큐(hardware dispatch queue)의 두 단계 큐 구조를 사용한다. 각 CPU는 로컬 소프트웨어 큐를 가지며, 락 경합 없이 I/O 요청을 추가할 수 있다. 소프트웨어 큐에서는 요청 병합(merging)과 스케줄링이 수행되고, 이후 하드웨어 큐를 통해 디바이스 드라이버에 전달된다.

  • 소프트웨어 스테이징 큐: blk_mq_ctx 구조로 표현되며, CPU별로 존재. 인접 섹터 요청의 병합(plugging)과 순서 재배치 수행
  • 하드웨어 디스패치 큐: blk_mq_hw_ctx 구조로 표현되며, 디바이스의 DMA 링 버퍼와 매핑. 하드웨어 태그 기반 완료 사용

I/O 스케줄러 동작 위치

blk-mq 아키텍처에서 I/O 스케줄러는 소프트웨어 스테이징 큐에 부착된다. 요청이 블록 레이어에 도착하면 직접 하드웨어 큐로 전달되려 시도하지만, 스케줄러가 있거나 요청 병합이 필요한 경우 소프트웨어 큐를 거친다. 이후 스케줄러가 순서를 결정한 후 하드웨어 큐로 디스패치된다.

I/O 우선순위 (ioprio)

리눅스 블록 계층은 cgroups v1(blkio)과 v2(io) 컨트롤러, 그리고 ioprio 우선순위 체계를 함께 사용한다. 다만 실제 가중치 기반 대역폭 분배를 가장 적극적으로 제공하는 스케줄러는 BFQ이며, none은 별도의 분배 기능 없이 blk-mq의 직접 디스패치 경로를 사용한다.

  • IOPRIO_CLASS_RT (실시간): 가장 높은 우선순위, 디스크 시간의 대부분을 독점
  • IOPRIO_CLASS_BE (일반): 기본 클래스, 가중치 기반 분배
  • IOPRIO_CLASS_IDLE (유휴): 나머지 시간에만 서비스

주요 튜너블

대표 스케줄러는 sysfs/sys/block/<dev>/queue/iosched 아래에서 서로 다른 조정 포인트를 제공한다. mq-deadline은 read_expire, write_expire, fifo_batch, writes_starved, front_merges로 읽기 지연시간과 배치 폭을 조정한다. BFQ는 low_latency, slice_idle, timeout_sync, max_budget으로 반응성과 처리량의 균형을 조절하고, Kyber는 read_lat_nsec, write_lat_nsec 두 값으로 읽기와 동기 쓰기의 목표 레이턴시를 제어한다.

비교/분석

I/O 스케줄러 비교표

특성 mq-deadline BFQ Kyber none
주요 목표 지연시간/throughput 균형 반응형 I/O, 대역폭 분배 저지연, 단순 구조 최소 오버헤드
알고리즘 기한 기반 배치 예산 기반 공정 큐잉 레이턴시 목표 기반 없음
소스 코드 크기 ~800 LOC ~10,500 LOC ~500 LOC ~100 LOC
per-I/O 오버헤드 0.7 μs 1.9 μs 0.5 μs <0.1 μs
최대 IOPS (i7) ~500K ~400K ~600K ~800K
cgroup 지원 기본 풀 계층 구조 기본 없음
디바이스 유형 범용 데스크톱/서버 NVMe/고속 NVMe/가상화
기능 읽기 우선, 기한 보장 대역폭 분배, 저지연 모드 레이턴시 쓰로틀 직접 디스패치

워크로드별 적합성

워크로드 권장 스케줄러 이유
데스크톱/노트북 BFQ 인터랙티브 앱 저지연 보장
데이터베이스 서버 mq-deadline 읽기 지연시간 균형
NVMe SSD 서버 Kyber 또는 none 낮은 오버헤드, 하드웨어 큐 활용
대용량 순차 I/O mq-deadline 또는 none 배치 처리 최적화
컨테이너/가상화 BFQ (cgroup) 그룹별 대역폭 제어
실시간 스트리밍 BFQ 소프트웨어 실시간 저지연

스케줄러 선택 및 전환

# 현재 스케줄러 확인
cat /sys/block/sda/queue/scheduler
# 출력 예: [mq-deadline] kyber bfq none

# 스케줄러 변경 (즉시 적용)
echo bfq > /sys/block/sda/queue/scheduler

# 기본 스케줄러 설정 (커널 파라미터)
# /etc/default/grub: elevator=bfq 또는 scsi_mod.use_blk_mq=1

동작 원리

I/O 스케줄러 동작 흐름

mq-deadline 동작 원리

mq-deadline은 요청마다 기한(deadline)을 설정하고, 기한이 임박한 요청을 우선 전달하는 단순하면서 효과적인 알고리즘이다.

  1. 기한 설정: 읽기 요청은 read_expire(기본 500ms), 쓰기 요청은 write_expire(기본 5000ms)만큼의 기한 할당
  2. 읽기 우선: 읽기 요청이 쓰기보다 우선 dispatched되지만, writes_starved회 이후 쓰기도 서비스
  3. 배치 처리: fifo_batch 개의 요청을 같은 방향으로 배치 처리하여 탐색 비용 절감
  4. 전방 병합: front_merges로 인접 섹터 요청의 전방 병합 제어

BFQ 동작 원리

BFQ는 예산 기반 공정 큐잉(Budget Fair Queueing) 알고리즘으로, 각 프로세스(큐)에 섹터 수 기반의 예산을 할당하고 B-WF2Q+ 스케줄링을 수행한다.

  1. 예산 할당: 각 큐에 섹터 수 기준 예산을 할당하고 디스패치마다 예산 차감
  2. 큐 만료: 예산 소진, 큐 빔, 예산 타임아웃 중 하나 발생 시 서비스 중단
  3. 장치 유휴: 동기 순차 I/O에서는 짧은 idling으로 공정성과 응답성을 보조
  4. 저지연 휴리스틱: 인터랙티브/소프트웨어 실시간 앱 감지 후 가중치 상향(weight-raising)
  5. 조기 큐 병합(EQM): 교차 I/O 수행 시 cooperating 프로세스 감지 및 큐 병합
  6. B-WF2Q+: O(log N) 복잡도의 증강 rb-tree로 이상적 공정 서비스와의 편차 최소화

Kyber 동작 원리

Kyber는 목표 레이턴시를 기반으로 요청을 쓰로틀링하는 단순한 스케줄러이다.

  1. 목표 레이턴시 설정: read_lat_nsec(읽기), write_lat_nsec(쓰기)로 목표 지연시간 지정
  2. 지연시간 기반 쓰로틀링: 현재 레이턴시가 목표를 초과하면 요청 전달 지연
  3. 최소 큐잉: 디바이스에 최소한의 요청만 유지하여 하드웨어 병렬성 활용

none (스케줄러 없음)

blk-mq의 직접 디스패치 모드로, 소프트웨어 큐에서 순서 재배치 없이 하드웨어 큐로 전달한다. NVMe SSD처럼 하드웨어 내부에서 효율적인 요청 재ordering이 가능한 디바이스에 적합하다.

장단점

mq-deadline

장점 단점
낮은 오버헤드 (0.7μs/request) 대역폭 분배 기능 부족
읽기/쓰기 균형 잡힌 지연시간 cgroup 계층 구조 지원 제한
범용 디바이스에 적합 고정밀 QoS 보장 어려움
단순하고 안정적인 알고리즘

BFQ

장점 단점
높은 시스템 반응성 높은 오버헤드 (1.9μs/request)
대역폭 기반 공정 분배 대량 IOPS 환경에서 병목 가능
cgroup v1/v2 풀 계층 지원 디스크 IOPS 한계 존재
인터랙티브/실시간 앱 최적화 단일 디스크에서만 idling 유용

Kyber

장점 단점
매우 낮은 오버헤드 최소한의 기능만 제공
NVMe SSD에 최적화 하드 디스크에서 성능 저하
단순한 설정 (2개 튜너블) 대역폭 분배 미지원
빠른 디스패치 cgroup 계층 구조 미지원

none

장점 단점
최소 오버헤드 순서 재배치 없음
NVMe 하드웨어 큐 최대 활용 하드 디스크에서 극심한 성능 저하
가상화 환경에 적합 대역폭 제어 기능 없음

관련 기술

표준 및 사양

  • blk-mq: Linux 3.13 도입, 메인스트림 I/O 스택 재설계 (Jens Axboe)
  • BFQ: P. Valente et al., "Evolution of the BFQ Storage I/O Scheduler", MST-2015
  • Kyber: Linux 4.12 도입, 읽기/동기 쓰기 목표 레이턴시 기반 제어
  • mq-deadline: blk-mq 환경의 대표 범용 스케줄러, 읽기 지연시간과 배치 처리 균형에 초점

관련 기술

참고 문헌

  • Valente, P., Avanzini, A. "Evolution of the BFQ Storage I/O Scheduler", MST-2015
  • Valente, P., Andreolini, M. "Improving Application Responsiveness with the BFQ Disk I/O Scheduler", SYSTOR '12
  • Linux Kernel Documentation: Documentation/block/bfq-iosched.rst
  • Linux Kernel Documentation: Documentation/block/deadline-iosched.rst
  • Linux Kernel Documentation: Documentation/block/kyber-iosched.rst
  • Linux Kernel Documentation: Documentation/block/blk-mq.rst
  • Linux Kernel Documentation: Documentation/block/switching-sched.rst

핵심 정리

리눅스 블록 레이어의 I/O 스케줄러는 blk-mq 멀티큐 아키텍처 위에서 동작하며, mq-deadline, BFQ, Kyber, none의 네 가지 선택지가 제공된다. mq-deadline은 낮은 오버헤드로 읽기/쓰기 지연시간 균형을 맞추어 범용 디바이스에 적합하고, BFQ는 예산 기반 공정 큐잉과 저지연 휴리스틱으로 데스크톱/서버 환경의 인터랙티브 워크로드에 최적화되어 있다. Kyber는 목표 레이턴시 기반 쓰로틀링으로 NVMe SSD에 적합하며, none은 스케줄링 없이 디바이스 하드웨어의 내재적 병렬성을 최대한 활용한다. 시스템의 워크로드와 스토리지 디바이스 유형에 따라 적절한 스케줄러를 선택하는 것이 I/O 성능 최적화의 핵심이며, sysfs를 통해 런타임에 자유롭게 전환할 수 있다.