ext4文件系统的delalloc选项造成单次写延迟增加的分析
最近我們的服務(wù)進(jìn)程遇到kill -15后處于Z的狀態(tài),變?yōu)榱私┦M(jìn)程,經(jīng)過(guò)/proc/{thread_id}/stack查看其上線(xiàn)程的棧,發(fā)現(xiàn)是卡在了fwrite的過(guò)程中,而我們的系統(tǒng)中所有文件系統(tǒng)掛載參數(shù)都使用了delalloc參數(shù),懷疑是這個(gè)原因:ext4掛載的時(shí)候打開(kāi)了delalloc選項(xiàng),然后系統(tǒng)在沒(méi)有分配磁盤(pán)塊的情況下寫(xiě)寫(xiě)寫(xiě),到page cache被回寫(xiě)到磁盤(pán)時(shí),發(fā)現(xiàn)磁盤(pán)已經(jīng)滿(mǎn)了,沒(méi)辦法分配新的磁盤(pán)塊了,就Hang住了。
?
這篇文章是淘寶內(nèi)核組的劉崢同學(xué)在內(nèi)部技術(shù)論壇上發(fā)表的一篇文章,但是由于劉崢同學(xué)目前沒(méi)有blog,征得本人同意,貼在我的blog上,如果大家喜歡,請(qǐng)去新浪微博關(guān)注他。:)
日前線(xiàn)上在升級(jí)到Ext4文件系統(tǒng)后出現(xiàn)應(yīng)用寫(xiě)操作延遲開(kāi)銷(xiāo)增大的問(wèn)題。造成這一問(wèn)題的根源目前已經(jīng)查明,是由于Ext4文件系統(tǒng)的一個(gè)新特性——Delay Allocation造成的。(后面簡(jiǎn)稱(chēng)delalloc)
在詳細(xì)分析這一問(wèn)題之前,先來(lái)介紹一下Ext4文件系統(tǒng)的delalloc特性。這一特性簡(jiǎn)要概括起來(lái)就是將以前在buffer IO中每次寫(xiě)操作都會(huì)涉及的磁盤(pán)塊分配過(guò)程推遲到數(shù)據(jù)回寫(xiě)時(shí)再進(jìn)行。我們知道,在進(jìn)行Buffer Write時(shí),系統(tǒng)的實(shí)際操作僅僅是為這些數(shù)據(jù)在操作系統(tǒng)內(nèi)分配內(nèi)存頁(yè)(page cache)并保存這些數(shù)據(jù),等待用戶(hù)調(diào)用fsync等操作強(qiáng)制刷新或者等待系統(tǒng)觸發(fā)定時(shí)回寫(xiě)過(guò)程。在數(shù)據(jù)拷貝到page cache這一過(guò)程中,系統(tǒng)會(huì)為這些數(shù)據(jù)在磁盤(pán)上分配對(duì)應(yīng)的磁盤(pán)塊。
而在使用delalloc后,上面的流程會(huì)略有不同,在每次Buffer Write時(shí),數(shù)據(jù)會(huì)被保存到page cache中,但是系統(tǒng)并不會(huì)為這些數(shù)據(jù)分配相應(yīng)的磁盤(pán)塊,僅僅會(huì)查詢(xún)是否有已經(jīng)為這些數(shù)據(jù)分配過(guò)磁盤(pán)塊,以便決定后面是否需要為這些數(shù)據(jù)分配磁盤(pán)塊。在用戶(hù)調(diào)用fsync或者系統(tǒng)觸發(fā)回寫(xiě)過(guò)程時(shí),系統(tǒng)會(huì)嘗試為標(biāo)記需要分配磁盤(pán)塊的這些數(shù)據(jù)分配磁盤(pán)塊。這樣,文件系統(tǒng)可以為這些屬于同一個(gè)文件的數(shù)據(jù)分配盡量連續(xù)的磁盤(pán)空間,從而優(yōu)化后續(xù)文件的訪(fǎng)問(wèn)性能(因?yàn)閭鹘y(tǒng)機(jī)械硬盤(pán)順序讀寫(xiě)的性能要比隨機(jī)讀寫(xiě)好很多)。
了解完delalloc特性的工作過(guò)程后,我們開(kāi)始分析線(xiàn)上遇到的問(wèn)題。線(xiàn)上應(yīng)用的I/O模式可以簡(jiǎn)化為一個(gè)單線(xiàn)程追加寫(xiě)操作的程序,每秒寫(xiě)入2、3M數(shù)據(jù),寫(xiě)操作后等待系統(tǒng)自動(dòng)將數(shù)據(jù)回寫(xiě)到磁盤(pán)。在使用delalloc后,每次Buffer Write操作,系統(tǒng)都會(huì)去查詢(xún)數(shù)據(jù)是否分配了磁盤(pán)塊,這一過(guò)程需要獲得一把讀鎖 (i_data_sem)。由于這時(shí)還沒(méi)有觸發(fā)回寫(xiě)操作,因此可以順利獲取i_data_sem,系統(tǒng)完成數(shù)據(jù)拷貝工作,并返回。由于僅僅是內(nèi)存拷貝的過(guò)程,所以這一操作速度相當(dāng)快。當(dāng)系統(tǒng)開(kāi)始進(jìn)行回寫(xiě)操作時(shí),系統(tǒng)會(huì)成批為數(shù)據(jù)分配磁盤(pán)塊,這一過(guò)程同樣需要獲取i_data_sem,并且需要加寫(xiě)鎖?以保證數(shù)據(jù)的一致性。由于使用delalloc后,需要分配的磁盤(pán)塊比nodelalloc情況下多很多(nodelalloc情況下每5秒文件系統(tǒng)會(huì)提交日志觸發(fā)回寫(xiě);delalloc情況下,系統(tǒng)會(huì)在約每30秒左右觸發(fā)一次回寫(xiě)),因此這一延遲時(shí)間較長(zhǎng)。如果這時(shí)應(yīng)用程序進(jìn)行一次Buffer Write,則該操作在嘗試獲得i_data_sem時(shí)會(huì)等待上述磁盤(pán)塊分配完成。由此造成寫(xiě)操作等待很長(zhǎng)時(shí)間,從而影響應(yīng)用程序的響應(yīng)延遲。
在上面的分析中已經(jīng)提到,delalloc是將多次磁盤(pán)塊分配的過(guò)程合并到一次中來(lái)進(jìn)行,那么是否真如預(yù)想的那樣,delalloc的平均延遲會(huì)小于nodelalloc的情況呢?我們使用fio來(lái)做如下測(cè)試:設(shè)置bs=4k,單線(xiàn)程每秒追加寫(xiě)入5M,程序運(yùn)行3分鐘,我們來(lái)看一下最后fio對(duì)延遲的統(tǒng)計(jì)結(jié)果:
delalloc:
lat (usec): min=2 , max=193466 , avg= 5.86, stdev=227.91
nodelalloc:
lat (usec): min=3 , max=16388 , avg= 7.00, stdev=28.92
從上面的統(tǒng)計(jì)結(jié)果看,寫(xiě)操作的平均延遲:打開(kāi)delalloc后為5.86us,關(guān)閉delalloc后為7.00us;最小延遲delalloc為2us,nodelalloc為3us;但是最大延遲delalloc為193.466ms,nodelalloc下僅為16.388ms。可見(jiàn)delalloc確實(shí)將多個(gè)寫(xiě)操作請(qǐng)求集中到了一起來(lái)進(jìn)行。因此在提供較低平均延遲的情況下,會(huì)造成某次寫(xiě)操作的延遲較大。
通過(guò)上面的分析可以看到,目前會(huì)受到Ext4的delalloc特性影響的應(yīng)用必須具備如下條件:
0. Buffer IO
1. 寫(xiě)操作過(guò)程中會(huì)涉及磁盤(pán)塊的分配,主要是記錄日志這類(lèi)追加寫(xiě)操作;
2. 每次寫(xiě)操作后沒(méi)有刷新數(shù)據(jù),而是等待系統(tǒng)自動(dòng)進(jìn)行回寫(xiě);
3. 對(duì)延遲有較高要求。
解決方法:關(guān)閉delalloc
1. mount -t ext4 -o remount,nodelalloc /${dev} /${mnt};
2. 編輯/etc/fstab中相關(guān)mount項(xiàng),添加nodelalloc掛載參數(shù)
轉(zhuǎn)載于:https://www.cnblogs.com/cobbliu/p/5603472.html
總結(jié)
以上是生活随笔為你收集整理的ext4文件系统的delalloc选项造成单次写延迟增加的分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python安卓手机编程入门自学_编程入
- 下一篇: mysql语录错误1300_mysql