這篇文章中缚陷,將會(huì)介紹Linux上常見(jiàn)的IO Scheduler,以及如何修改Linux上面的默認(rèn)的IO Scheduler。在翻譯的過(guò)程中,對(duì)原文的內(nèi)容有所刪減撵幽,有些地方也重寫(xiě)排列了一下順序是牢。
原文鏈接: Improving Linux System Performance with I/O Scheduler Tuning
什么是IO調(diào)度器僵井?
磁盤(pán)的訪問(wèn)速度,一直都是計(jì)算機(jī)的瓶頸驳棱。盡管現(xiàn)在固態(tài)硬盤(pán)的出現(xiàn)批什,緩解了一下這個(gè)尷尬的狀況。但是社搅,磁盤(pán)的訪問(wèn)速度依然是系統(tǒng)中的瓶頸驻债。
對(duì)于機(jī)械硬盤(pán)來(lái)說(shuō),當(dāng)我們需要訪問(wèn)硬盤(pán)上的數(shù)據(jù)的時(shí)候形葬,首先需要經(jīng)過(guò)一個(gè)被稱(chēng)為尋道時(shí)間的過(guò)程合呐,即,將盤(pán)片旋轉(zhuǎn)到特定的扇區(qū)笙以,然后由磁頭來(lái)讀取數(shù)據(jù)合砂。一般來(lái)說(shuō),這個(gè)尋道時(shí)間會(huì)占硬盤(pán)訪問(wèn)時(shí)間中的很大比重源织。
IO調(diào)度器就是為了優(yōu)化這個(gè)過(guò)程翩伪,而工作的。IO調(diào)度器谈息,一般是將訪問(wèn)磁盤(pán)上相鄰數(shù)據(jù)的請(qǐng)求缘屹,放在一起處理,進(jìn)而減少無(wú)謂的尋道時(shí)間侠仇,提高速度轻姿。
在Linux系統(tǒng)上犁珠,已經(jīng)存在了好多個(gè)IO調(diào)度器。它們都有各自的特色互亮。在這篇文章剩下的部分里犁享,我們將會(huì)依次介紹這幾個(gè)IO調(diào)度器,并比較他們的性能豹休。
修改IO調(diào)度器
在本文中炊昆,我們使用Ubuntu來(lái)做實(shí)驗(yàn),因?yàn)樵赨buntu中威根,我們既可以在運(yùn)行時(shí)修改IO調(diào)度器凤巨,也可以在啟動(dòng)時(shí)就修改IO調(diào)度器。
如果想要在運(yùn)行時(shí)修改IO調(diào)度器洛搀,只需要修改一個(gè)位于/sys目錄中的文件的值敢茁,就可以了。
如果想要在啟動(dòng)時(shí)修改IO調(diào)度器留美,那么需要在啟動(dòng)時(shí)彰檬,修改GRUB項(xiàng)。
在修改IO調(diào)度器之前谎砾,我們先查看一下當(dāng)前系統(tǒng)中的IO調(diào)度器逢倍。通過(guò)讀取/sys/block/<disk device>/queue/scheduler這個(gè)文件的內(nèi)容來(lái)獲取。
# cat /sys/block/sda/queue/scheduler
noop [deadline] cfq
上面的輸出棺榔,說(shuō)明sda這個(gè)磁盤(pán)的IO調(diào)度器為deadline.
盡管IO調(diào)度器是內(nèi)核級(jí)別的參數(shù)瓶堕,但是隘道,可以分別為不同的磁盤(pán)設(shè)置不同的IO調(diào)度器症歇。如果我們修改sda的IO調(diào)度器,sda上面的全部的文件系統(tǒng)都會(huì)使用這個(gè)新的IO調(diào)度器谭梗。
正如性能調(diào)優(yōu)的一般步驟那樣忘晤,我們需要先了解我們要進(jìn)行調(diào)優(yōu)的環(huán)境,然后根據(jù)測(cè)試結(jié)果選擇一個(gè)合適的IO調(diào)度器激捏。
在運(yùn)行時(shí)修改IO調(diào)度器
只需要修改/sys/block/<diskdevice>/queue/scheduler這個(gè)文件的內(nèi)容:
# echo "cfq" > /sys/block/sda/queue/scheduler
# cat /sys/block/sda/queue/scheduler
noop deadline [cfq]
從上面的輸出結(jié)果中我們可以看到设塔,IO調(diào)度器被馬上替換為CFQ。這也就意味著远舅,我們并不需要重啟我們的PostgreSQL實(shí)例或者其他的服務(wù)來(lái)進(jìn)行測(cè)試闰蛔。
啟動(dòng)時(shí)修改IO調(diào)度器
編輯/etc/default/grub,找到GRUB_CMDLINE_LINUX這一項(xiàng)图柏。將它修改成下面這樣序六,告訴它使用noop這個(gè)IO調(diào)度器。
GRUB_CMDLINE_LINUX="elevator=noop"
然后蚤吹,運(yùn)行update-grub2命令來(lái)使設(shè)置生效例诀。
# update-grub2
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.4.0-62-generic
Found initrd image: /boot/initrd.img-4.4.0-62-generic
Found linux image: /boot/vmlinuz-4.4.0-57-generic
Found initrd image: /boot/initrd.img-4.4.0-57-generic
done
通過(guò)reboot命令重啟系統(tǒng)之后随抠,我們可以查看我們的設(shè)置是否生效。
# cat /sys/block/sda/queue/scheduler
[noop] deadline cfq
測(cè)試PostgreSQL在不同IO調(diào)度器下的性能
CFQ
CFQ的全稱(chēng)是Complete Fairness Queueing繁涂,它的工作原理是這樣的拱她,它先創(chuàng)建一個(gè)IO請(qǐng)求隊(duì)列,然后在對(duì)隊(duì)列中的請(qǐng)求根據(jù)上文我們說(shuō)到的那種方式扔罪,即將要訪問(wèn)磁盤(pán)上相鄰數(shù)據(jù)的請(qǐng)求放到一起秉沼,按照這種方式進(jìn)行排序之后,再依次處理IO請(qǐng)求隊(duì)列中的請(qǐng)求步势。
我們可以看到氧猬,CFQ實(shí)際上并沒(méi)有區(qū)分不同優(yōu)先級(jí)的IO請(qǐng)求。這也就意味著坏瘩,在某些需要優(yōu)先處理某些請(qǐng)求的場(chǎng)合盅抚,它并不適合。
在理解了CFQ之后倔矾,我們通過(guò)pgbench來(lái)測(cè)試我們的PostgreSQL實(shí)例妄均。
# su - postgres
$ pgbench -c 100 -j 2 -t 1000 example
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 50
query mode: simple
number of clients: 100
number of threads: 2
number of transactions per client: 1000
number of transactions actually processed: 100000/100000
latency average: 60.823 ms
tps = 1644.104024 (including connections establishing)
tps = 1644.228715 (excluding connections establishing)
從結(jié)果中,我們可以看到哪自,現(xiàn)在的tps基本上是1644/s丰包。盡管不是一個(gè)非常差的結(jié)果,但是這個(gè)結(jié)果并不是最優(yōu)的壤巷。
Deadline
Deadline調(diào)度器邑彪,會(huì)創(chuàng)建兩個(gè)隊(duì)列,一個(gè)讀隊(duì)列胧华,一個(gè)寫(xiě)隊(duì)列寄症。并且每個(gè)IO請(qǐng)求都會(huì)有一個(gè)與其相關(guān)聯(lián)的過(guò)期時(shí)間戳。
當(dāng)Deadline調(diào)度器在處理IO請(qǐng)求的時(shí)候矩动,它會(huì)通過(guò)過(guò)期時(shí)間戳來(lái)對(duì)IO請(qǐng)求進(jìn)行優(yōu)先級(jí)排序有巧。那些將要過(guò)期的IO請(qǐng)求會(huì)被賦予更高的優(yōu)先級(jí)。
默認(rèn)情況下悲没,Deadline為讀請(qǐng)求設(shè)置的過(guò)期時(shí)間為500ms篮迎,而為寫(xiě)請(qǐng)求設(shè)置的過(guò)期時(shí)間則為5000ms。我們可以看到示姿,Deadline實(shí)際上比較適合于那種讀請(qǐng)求比寫(xiě)請(qǐng)求多好多的場(chǎng)景中甜橱。
我們將IO調(diào)度器修改成Deadline,然后查看PostgreSQL的性能栈戳。
# echo deadline > /sys/block/sda/queue/scheduler
# cat /sys/block/sda/queue/scheduler
noop [deadline] cfq
現(xiàn)在我們已經(jīng)將IO調(diào)度器修改成了Deadline岂傲,我們?cè)俅螠y(cè)試系統(tǒng)的性能:
# su - postgres
$ pgbench -c 100 -j 2 -t 1000 example
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 50
query mode: simple
number of clients: 100
number of threads: 2
number of transactions per client: 1000
number of transactions actually processed: 100000/100000
latency average: 46.700 ms
tps = 2141.318132 (including connections establishing)
tps = 2141.489076 (excluding connections establishing)
我們可以看到,相對(duì)與CFQ荧琼,TPS有接近500/s的提升譬胎。
我們同樣可以看到秉撇,盡管pgbench在測(cè)試時(shí)餐塘,基本上按照1:1的比例生成讀寫(xiě)請(qǐng)求,但是依舊可以從Deadline調(diào)度器中受益。
Noop
Noop調(diào)度器是一個(gè)非常特殊的調(diào)度器洪囤。它并不會(huì)對(duì)特殊請(qǐng)求進(jìn)行優(yōu)先處理废菱,與此相反搀继,它將全部的IO請(qǐng)求都放到一個(gè)FIFO隊(duì)列中吟策。但是,它還會(huì)對(duì)相似的請(qǐng)求進(jìn)行合并苟翻。
Noop調(diào)度器是為了那些實(shí)際上并不需要任何IO調(diào)度器的系統(tǒng)而進(jìn)行優(yōu)化的韵卤。比如,在那些虛擬機(jī)實(shí)例中崇猫,實(shí)際的IO請(qǐng)求都是由宿主機(jī)處理的沈条。
在虛擬機(jī)場(chǎng)景中,因?yàn)樗拗鳈C(jī)上诅炉,實(shí)際上已經(jīng)有了IO調(diào)度器了蜡歹。所以,在這種場(chǎng)景中涕烧,每個(gè)IO請(qǐng)求都會(huì)被傳遞到兩個(gè)IO調(diào)度器中月而,一個(gè)是VM的調(diào)度器,一個(gè)是宿主機(jī)上的IO調(diào)度器议纯。
# echo noop > /sys/block/sda/queue/scheduler
# cat /sys/block/sda/queue/scheduler
[noop] deadline cfq
# su - postgres
$ pgbench -c 100 -j 2 -t 1000 example
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 50
query mode: simple
number of clients: 100
number of threads: 2
number of transactions per client: 1000
number of transactions actually processed: 100000/100000
latency average: 46.364 ms
tps = 2156.838618 (including connections establishing)
tps = 2157.102989 (excluding connections establishing)
從結(jié)果中父款,我們可以看到,僅僅只是比Deadline調(diào)度器的結(jié)果好一點(diǎn)點(diǎn)瞻凤。
由于我們的這次測(cè)試是在虛擬機(jī)中進(jìn)行的憨攒,所以,盡管修改了虛擬機(jī)上面的IO調(diào)度器鲫构,實(shí)際上起作用的還是宿主機(jī)上的IO調(diào)度器浓恶。