Linux I/O 스케줄러 튜닝: mq-deadline, 없음, BFQ
16분 소요 - 2026년 6월 1일

Sysfs 명령, udev 규칙 및 fio 벤치마킹 단계를 통해 NVMe, SATA 및 HDD 워크로드에 적합한 Linux I/O 스케줄러를 선택하고 조정하는 방법을 설명합니다.
Linux I/O 스케줄러 튜닝: mq-deadline, none, BFQ
Linux I/O 스케줄러는 읽기 및 쓰기 요청이 스토리지 장치에 도달하는 순서를 결정하며, 올바른 선택은 거의 전적으로 하드웨어에 달려 있습니다. none NVMe의 경우, mq-deadline 혼합 워크로드를 실행하는 SATA SSD 및 HDD에는를, bfq 다른 프로세스의 리소스 부족을 방지해야 할 때 사용하십시오. 이 가이드에서는 세 가지 주요 스케줄러의 작동 방식, 워크로드에 맞는 스케줄러 선택 방법, 그리고 튜닝 및 결과 확인 방법을 다룹니다.
읽기 전에 직접 실습해 보고 싶다면, 이 동영상에서 터미널을 통해 스케줄러를 전환하고 테스트하는 기본 방법을 확인할 수 있습니다.
mq-deadline, none, BFQ의 차이점
각 스케줄러는 서로 다른 전략으로 요청을 처리합니다. 이들의 차이점을 파악해야만 부팅 시 커널이 임의로 선택한 설정을 그대로 사용하는 대신, 의도적으로 적절한 스케줄러를 선택할 수 있습니다.
mq-deadline
이 mq-deadline 스케줄러는 어떤 요청도 무한정 대기하지 않도록 보장합니다. 이 스케줄러는 읽기와 쓰기를 위해 각각 정렬된 큐를 별도로 유지하며, 시크(seek) 시간을 줄이기 위해 논리 블록 주소(LBA) 순서로 정렬하고, 기본적으로 읽기는 500ms, 쓰기는 5초의 데드라인을 적용합니다. 요청이 데드라인에 도달하면 큐의 맨 앞으로 이동합니다.
읽기 작업은 일반적으로 애플리케이션을 차단하는 반면, 쓰기 작업은 비동기적으로 처리되므로 읽기가 쓰기보다 우선순위를 가집니다. 쓰기 작업이 완전히 차단되는 것을 방지하기 위해, 스케줄러는 정해진 횟수의 읽기 작업이 수행된 후 기한이 지난 쓰기 작업 묶음을 처리합니다. 그 결과 일관된 낮은 지연 시간을 제공하므로, 데이터베이스 서버나 읽기와 쓰기가 혼합된 모든 워크로드에 매우 적합합니다.
없음
이 none 스케줄러는 거의 아무것도 하지 않습니다. 재순서화, 병합 또는 우선순위 지정 없이 요청을 선입선출(FIFO) 순서대로 장치에 바로 전달합니다. 이는 자체 내부 큐를 관리하고 수만 개의 진행 중인 요청을 한 번에 추적할 수 있는 최신 NVMe 드라이브에 적합합니다. 소프트웨어 스케줄링 계층을 제거하면 애플리케이션에서 장치까지 가능한 가장 짧은 경로가 확보되는데, 이는 바로 높은 처리량을 요구하는 NVMe 워크로드가 원하는 바입니다.
단, 이는 하드웨어가 자체적으로 지능적으로 스케줄링할 수 있을 때만 유효합니다. 큐 용량이 얕은 HDD나 SATA SSD의 경우, 소프트웨어 재순서화를 생략하면 성능이 향상되기보다는 오히려 저하되는 경우가 많습니다.
BFQ
BFQ(Budget Fair Queuing)는 공정성을 최우선으로 합니다. 시간 슬라이스 대신 각 프로세스에 디스크 섹터 단위로 측정된 예산을 할당합니다. 대용량 순차 읽기 작업에는 처리량을 유지하기 위해 더 큰 예산이 할당되고, 지연 시간에 민감한 작업에는 신속하게 처리될 수 있도록 더 작은 예산이 할당되며, 피드백 루프를 통해 실행 중에 예산이 조정됩니다.
BFQ는 과부하 상태에서도 대화형 작업의 응답성을 유지하므로, 백그라운드에서 대용량 파일 전송이 진행되는 동안에도 동영상 재생이나 데이터베이스 쿼리가 원활하게 유지됩니다. 이러한 공정성은 CPU 자원을 소모합니다. 요청당 오버헤드는 약 1.9마이크로초로, mq-deadline의 약 3배에 달하며, 속도가 느린 ARM 코어에서는 이 오버헤드로 인해 처리량이 빠른 x86 칩에서 동일한 스케줄러가 달성하는 수준보다 훨씬 낮아집니다. 순수한 처리량과 CPU 효율성이 가장 중요한 서버 환경에서는 이러한 절충점을 정당화하기 어렵습니다.
| 스케줄러 | 알고리즘 | CPU 오버헤드 | 최적의 하드웨어 | 주요 목표 |
|---|---|---|---|---|
mq-deadline | 마감 시간이 지정된 정렬된 LBA | 낮음 (~0.7 µs/요청) | SATA SSD, HDD, 가상 디스크 | 예측 가능한 낮은 지연 시간 |
none | FIFO, 재순서화 없음 | 미미함 | NVMe SSD | 최대 처리량 |
bfq | 비례 할당 예산 | 보통 (~1.9 µs/요청) | HDD, 공유 및 데스크톱 시스템 | 공정성 및 응답성 |
워크로드에 적합한 스케줄러 선택
적합한 스케줄러를 결정하는 요소는 두 가지입니다: 스토리지 하드웨어와 애플리케이션의 액세스 패턴입니다. 먼저 하드웨어부터 살펴보겠습니다. 펌웨어 기능이 있는 NVMe 드라이브처럼 장치가 이미 요청을 재정렬하는 경우, 소프트웨어 스케줄링은 오버헤드만 증가시키므로 none 소프트웨어 스케줄링이 유리합니다. 시크 타임이 지배적인 회전식 HDD의 경우, 소프트웨어 재순서가 지연 시간을 줄여주므로 mq-deadline 또는 bfq 가 더 나은 선택입니다. SATA SSD는 그 중간에 위치합니다. HDD보다 빠르지만 NVMe의 깊은 큐는 없기 때문에, 이 경우에는 mq-deadline 적합합니다.
다른 요소가 이미 스케줄링을 수행하고 있는 경우에도 동일한 논리가 적용됩니다. virtio-blk를 사용하는 게스트 VM은 호스트에 의존하여 I/O를 스케줄링하며, 쓰기 후 캐시(write-back cache)를 갖춘 하드웨어 RAID 컨트롤러는 자체적으로 순서를 최적화합니다. 두 경우 모두 none 작업에 대한 비용을 두 번 지불하는 것을 피합니다.
두 번째 요소는 액세스 패턴입니다. 초당 수천 건의 4K 무작위 읽기를 수행하는 데이터베이스는 NVMe 어레이에서 대용량 순차 블록을 스트리밍하는 훈련 작업과는 전혀 다르며, 각각 다른 스케줄러가 필요합니다. 아래 표는 일반적인 워크로드를 시작점으로 매핑한 것입니다.
| 워크로드 | 스토리지 | 스케줄러 | 이유 |
|---|---|---|---|
| AI/ML 훈련 | NVMe SSD | none | 순차적 높은 처리량; 펌웨어가 큐잉 처리 |
| OLTP 데이터베이스 | NVMe SSD | none | 저지연 랜덤 I/O; 소프트웨어 오버헤드 방지 |
| OLTP 데이터베이스 | SATA SSD | mq-deadline | 쓰기 대기 현상 방지; 예측 가능한 테일 지연 시간 |
| 데이터 웨어하우스 / OLAP | NVMe / 고속 SSD | none | 심층 병렬 큐; 최대 처리량 |
| 일반 웹 호스팅 | SATA SSD / HDD | mq-deadline | 다양한 소형 파일 I/O에 대한 일관된 응답 |
| 공유/다중 테넌트 호스팅 | HDD / SSD | bfq | 테넌트 간 형평성 보장; I/O 독점 방지 |
| 가상 머신 게스트 | virtio-blk | none | 호스트가 이미 스케줄링함; 이중 스케줄링은 CPU 낭비 |
| 백업 / 아카이브 | HDD | mq-deadline | 스타베이션 방지 기능이 적용된 순차 처리량 |
주목할 만한 예외가 하나 있습니다. 금융 시스템과 같이 p99 또는 p999의 테일 지연 시간을 중요 지표로 삼는 경우, NVMe에서도 mq-deadline 이 none 엄격한 마감 시간을 적용하고 가끔 발생하는 요청 지연을 방지함으로써
스케줄러 매개변수 변경 및 조정
스케줄러 전환과 매개변수 조정은 모두 sysfs를 통해 이루어지며, 변경 사항을 테스트하기 위해 재부팅할 필요가 없습니다.
활성 스케줄러 전환
장치에 대해 사용 가능한 스케줄러를 확인합니다. 괄호 안의 값이 활성 스케줄러입니다:
cat /sys/block/sda/queue/scheduler실행 중에 다른 스케줄러로 전환합니다. 이 변경 사항은 즉시 적용되지만 재부팅 후에는 유지되지 않습니다:
echo bfq | sudo tee /sys/block/sda/queue/scheduler만약 bfq 목록에 없다면, 먼저 모듈을 로드하십시오:
sudo modprobe bfq선택 사항을 영구적으로 적용하려면, RHEL 9 및 유사 릴리스에서는 더 이상 스케줄러를 변경하지 않는 구형 elevator= 커널 매개변수 대신 udev 규칙을 사용하십시오. RHEL 9 및 유사 릴리스에서는 더 이상 이 매개변수가 스케줄러를 변경하지 않습니다. 이 규칙은 mq-deadline 의 모든 비회전식 SCSI 디스크에 대해 /etc/udev/rules.d/60-io-scheduler.rules:
ACTION=="add|change", SUBSYSTEM=="block", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"재부팅 없이 다시 로드하고 적용하려면:
sudo udevadm control --reload-rules && sudo udevadm triggerRHEL 기반 시스템에서는 TuneD 프로필이 장치별 규칙 대신 시스템 전체 프로필을 통해 동일한 작업을 수행합니다.
조정할 가치가 있는 매개변수
각 스케줄러는 /sys/block/<device>/queue/iosched/. mq-deadline의 경우, 데드라인이 주요 조정 요소입니다. SATA SSD에 있는 지연 시간에 민감한 데이터베이스는 데드라인을 짧게 설정하는 것이 유리합니다:
echo 100 | sudo tee /sys/block/sda/queue/iosched/read_expire
echo 1000 | sudo tee /sys/block/sda/queue/iosched/write_expire반면 bfq 대역폭이 높은 시스템에서는 지연 시간 휴리스틱을 비활성화하면 처리량이 증가합니다:
echo 0 | sudo tee /sys/block/sda/queue/iosched/low_latency
echo 0 | sudo tee /sys/block/sda/queue/iosched/slice_idle| 스케줄러 | 매개변수 | 기본값 | 튜닝 목표 |
|---|---|---|---|
mq-deadline | read_expire | 500 ms | 더 빠른 읽기 응답을 위해 더 낮게 설정 |
mq-deadline | write_expire | 5000 ms | 쓰기 지연 시간을 줄이려면 더 낮게 설정 |
mq-deadline | writes_starved | 3 | 읽기 작업이 많은 부하에서는 값을 높입니다 |
mq-deadline | fifo_batch | 16 | 최소 지연 시간을 위해 1로 설정 |
bfq | low_latency | 1 | 최대 처리량을 위해 0으로 설정 |
bfq | slice_idle | 8 ms | SSD 또는 RAID의 경우 0으로 설정 |
bfq | strict_guarantees | 0 | 엄격한 대역폭 공유를 위해 1로 설정 |
공유 호스팅의 경우, BFQ는 cgroups v2와 잘 어울립니다. io.weight 값을 할당하면, 예를 들어 백업 작업보다 데이터베이스 프로세스에 10배 더 많은 I/O 할당량을 부여할 수 있어, 백그라운드 작업이 대화형 트래픽을 압도하는 것을 방지할 수 있습니다. 어떤 설정을 변경하든, BFQ의 높은 요청당 비용은 CPU에 부하가 걸리고 IOPS가 높은 시스템에서 누적되므로, 적용하기 전에 벤치마크를 수행하십시오.
튜닝 후 성능 확인
무언가를 변경하기 전에 항상 기준값을 기록해 두십시오. 기준값이 없으면 조정이 효과가 있었는지 확인할 방법이 없습니다.
fio는 이를 위한 표준 도구입니다. 이 도구는 블록 크기, 큐 깊이, I/O 엔진 설정을 통해 특정 워크로드 패턴을 재현합니다. 항상 --direct=1 매개변수를 전달하여 페이지 캐시를 우회하고, 캐시된 읽기 대신 스케줄러와 장치를 직접 측정하도록 해야 합니다. 테스트를 실제 워크로드에 맞추십시오:
| 워크로드 | fio 매개변수 |
|---|---|
| OLTP 데이터베이스 | --rw=randread --bs=4k --iodepth=32 --direct=1 |
| 데이터 웨어하우스 | --rw=read --bs=1m --iodepth=32 --direct=1 |
| 사전 기록 / 재실행 로그 | --rw=write --bs=4k --iodepth=1 --direct=1 |
| 오브젝트 스토리지 | --rw=randrw --bs=64k --iodepth=64 --direct=1 |
1에서 256까지의 값을 모두 적용하여 iodepth 1부터 256까지의 값에 대해 동일한 테스트를 실행하여, IOPS 증가가 멈추고 지연 시간이 급증하는 지점인 장치의 포화점을 확인하십시오. 변경 후 실시간 모니터링을 위해, iostat -x 1 중요한 메트릭을 보고합니다: r_await 그리고 w_await 읽기 및 쓰기 완료 지연 시간, aqu-sz 평균 큐 깊이, 그리고 %util 장치 사용률. %util 이 100% 근처에 머무르면 하드웨어가 한계이며 스케줄러를 변경해도 소용이 없습니다.
소프트웨어 비용과 하드웨어 비용을 구분하려면 btt와 함께 blktrace를 실행하십시오. 이 명령은 지연 시간을 소프트웨어 큐에서 소요되는 시간인 Q2D와, 장치가 요청을 처리하는 데 걸리는 시간인 D2C로 나눕니다. Q2D가 주를 이룬다면 스케줄러가 병목 지점입니다. D2C가 주를 이룬다면 하드웨어가 병목 지점입니다.
결과를 해석할 때 유의해야 할 점은, 스케줄러 선택은 주로 지연 시간 분포의 중앙값이 아닌 꼬리 부분을 결정한다는 것입니다. none NVMe로 mq-deadline 로 전환하면 중앙값 지연 시간은 몇 마이크로초 증가할 수 있지만, p99 및 p999 지연 시간은 절반으로 줄어들 수 있습니다. SLA에 구속되는 사용자 대상 서비스의 경우, 이러한 상충 관계는 거의 항상 그만한 가치가 있습니다. 바로 이 때문에 평균 처리량이 아닌 꼬리 부분의 지연 시간을 측정하는 것이 이 작업의 핵심입니다.
적합한 스케줄러 선택
스케줄러 튜닝은 알고리즘을 하드웨어 및 액세스 패턴에 맞춘 다음, 측정을 통해 그 효과를 입증하는 과정입니다. 요약하면 다음과 같습니다:
- NVMe:
none를 사용하고 큐잉은 펌웨어에 맡기십시오. - I/O가 혼합된 SATA SSD 및 HDD:
mq-deadline를 사용하여 예측 가능한 지연 시간을 확보하십시오. - 공유 또는 멀티 테넌트 호스트:
bfq를 사용하여 한 워크로드가 나머지 워크로드를 방해하지 않도록 하십시오. - 중앙값이 아닌 테일 지연 시간: 스케줄러 변경 사항은 p99 및 p999에 나타나므로, 이를 측정해야 합니다.
- 지속성을 확보하십시오: udev 규칙이나 TuneD를 사용하고, 절대 dead
elevator=매개 변수는 절대 사용하지 마십시오.
스케줄러의 성능을 최대한 활용하려면 이를 감당할 수 있는 하드웨어가 우선입니다. 높은 처리량과 낮은 지연 시간을 요구하는 워크로드를 위해 구축된 NVMe 기반 서버가 필요하다면, FDC의 VPS 옵션을 확인해 보십시오.
강력하고 계량되지 않는 VPS가 중요한 이유
미터링되지 않은 VPS는 고정된 포트 속도로 정액제 대역폭을 제공합니다. 계량형 요금제와 어떻게 다른지, 언제 요금이 부과되는지, 구매 전에 확인해야 할 사항은 무엇인지 알아보세요.
7분 소요 - 2025년 5월 9일
Linux 메모리 관리: 스왑, OOM 킬러 및 C그룹
12분 소요 - 2026년 5월 31일

질문이 있거나 맞춤형 솔루션이 필요하신가요?
유연한 옵션
글로벌 도달 범위
즉시 배포
유연한 옵션
글로벌 도달 범위
즉시 배포