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