共計(jì) 2403 個(gè)字符,預(yù)計(jì)需要花費(fèi) 7 分鐘才能閱讀完成。
本篇內(nèi)容介紹了“有哪些 Linux 磁盤緩存相關(guān)知識(shí)”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓丸趣 TV 小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
前言
最近遇到了一起跟磁盤相關(guān)的線上故障,借此總結(jié)一下之前不太了解的 Linux 磁盤緩存相關(guān)的知識(shí)。
總的來(lái)說(shuō)磁盤緩存出現(xiàn)的原因大概有兩個(gè):第一是訪問(wèn)磁盤的速度遠(yuǎn)慢于訪問(wèn)內(nèi)存的速度,通過(guò)在內(nèi)存中緩存磁盤內(nèi)容可以提高訪問(wèn)速度;第二是根據(jù)程序的局部性原理,數(shù)據(jù)一旦被訪問(wèn)過(guò),就很有可能在短時(shí)間內(nèi)再次被訪問(wèn),所以在內(nèi)存中緩存磁盤內(nèi)容可以提高程序運(yùn)行速度。
局部性原理
程序局部性原理:程序在執(zhí)行時(shí)呈現(xiàn)出局部性規(guī)律,即在一段時(shí)間內(nèi),整個(gè)程序的執(zhí)行僅限于程序中的某一部分。相應(yīng)地,執(zhí)行所訪問(wèn)的存儲(chǔ)空間也局限于某個(gè)內(nèi)存區(qū)域,具體來(lái)說(shuō),局部性通常有兩種形式:時(shí)間局部性和空間局部性。
時(shí)間局部性:被引用過(guò)一次的存儲(chǔ)器位置在未來(lái)會(huì)被多次引用。
空間局部性:如果一個(gè)存儲(chǔ)器的位置被引用,那么將來(lái)他附近的位置也會(huì)被引用。
頁(yè)緩存
Linux 系統(tǒng)中為了減少對(duì)磁盤的 IO 操作,會(huì)將打開(kāi)的磁盤內(nèi)容進(jìn)行緩存,而緩存的地方則是物理內(nèi)存,進(jìn)而將對(duì)磁盤的訪問(wèn)轉(zhuǎn)換成對(duì)內(nèi)存的訪問(wèn),有效提高程序的速度。Linux 的緩存方式是利用物理內(nèi)存緩存磁盤上的內(nèi)容,稱為頁(yè)緩存(page cache)。
頁(yè)緩存是由內(nèi)存中的物理頁(yè)面組成的,其內(nèi)容對(duì)應(yīng)磁盤上的物理塊。頁(yè)緩存的大小會(huì)根據(jù)系統(tǒng)的內(nèi)存空閑大小進(jìn)行動(dòng)態(tài)調(diào)整,它可以通過(guò)占用內(nèi)存以擴(kuò)張大小,也可以自我收縮以緩解內(nèi)存使用壓力。
在虛擬內(nèi)存機(jī)制出現(xiàn)以前,操作系統(tǒng)使用塊緩存系列,但是在虛擬內(nèi)存出現(xiàn)以后,操作系統(tǒng)管理 IO 的粒度更大,因此采用了頁(yè)緩存機(jī)制,頁(yè)緩存是基于頁(yè)的、面向文件的緩存機(jī)制。
頁(yè)緩存的讀取
Linux 系統(tǒng)在讀取文件時(shí),會(huì)優(yōu)先從頁(yè)緩存中讀取文件內(nèi)容,如果頁(yè)緩存不存在,系統(tǒng)會(huì)先從磁盤中讀取文件內(nèi)容更新到頁(yè)緩存中,然后再?gòu)捻?yè)緩存中讀取文件內(nèi)容并返回。
大致過(guò)程如下:
進(jìn)程調(diào)用庫(kù)函數(shù) read 發(fā)起讀取文件請(qǐng)求
內(nèi)核檢查已打開(kāi)的文件列表,調(diào)用文件系統(tǒng)提供的 read 接口
找到文件對(duì)應(yīng)的 inode,然后計(jì)算出要讀取的具體的頁(yè)
通過(guò) inode 查找對(duì)應(yīng)的頁(yè)緩存,1)如果頁(yè)緩存節(jié)點(diǎn)命中,則直接返回文件內(nèi)容;2)如果沒(méi)有對(duì)應(yīng)的頁(yè)緩存,則會(huì)產(chǎn)生一個(gè)缺頁(yè)異常(page fault)。這時(shí)系統(tǒng)會(huì)創(chuàng)建新的空的頁(yè)緩存并從磁盤中讀取文件內(nèi)容,更新頁(yè)緩存,然后重復(fù)第 4 步
讀取文件返回
所以說(shuō),所有的文件內(nèi)容的讀取,無(wú)論最初有沒(méi)有命中頁(yè)緩存,最終都是直接來(lái)源于頁(yè)緩存。
頁(yè)緩存的寫入
因?yàn)轫?yè)緩存的存在,當(dāng)一個(gè)進(jìn)程調(diào)用 write 時(shí),對(duì)文件的更新僅僅是被寫到了文件的頁(yè)緩存中,讓后將對(duì)應(yīng)的頁(yè)標(biāo)記為 dirty,整個(gè)過(guò)程就結(jié)束了。Linux 內(nèi)核會(huì)在周期性地將臟頁(yè)寫回到磁盤,然后清理掉 dirty 標(biāo)識(shí)。
由于寫操作只會(huì)把變更寫入頁(yè)緩存,因此進(jìn)程并不會(huì)因此為阻塞直到磁盤 IO 發(fā)生,如果此時(shí)計(jì)算機(jī)崩潰,寫操作的變更可能并沒(méi)有發(fā)生在磁盤上。所以對(duì)于一些要求比較嚴(yán)格的寫操作,比如數(shù)據(jù)系統(tǒng),就需要主動(dòng)調(diào)用 fsync 等操作及時(shí)將變更同步到磁盤上。讀操作則不同,read 通常會(huì)阻塞直到進(jìn)程讀取到數(shù)據(jù),而為了減少讀操作的這種延遲,Linux 系統(tǒng)還是用了“預(yù)讀”的技術(shù),即從磁盤中讀取數(shù)據(jù)時(shí),內(nèi)核將會(huì)多讀取一些頁(yè)到頁(yè)緩存中。
回寫線程
頁(yè)緩存的回寫是由內(nèi)核中的單獨(dú)的線程來(lái)完成的,回寫線程會(huì)在以下 3 種情況下進(jìn)行回寫:
空閑內(nèi)存低于閾值時(shí)。當(dāng)空閑內(nèi)存不足時(shí),需要釋放掉一部分緩存,由于只有不臟的頁(yè)才能被釋放,所以需要把臟頁(yè)都回寫到磁盤,使其變?yōu)榭苫厥盏母蓛舻捻?yè)。
臟頁(yè)在內(nèi)存中處理時(shí)間超過(guò)閾值時(shí)。這是為了確保臟頁(yè)不會(huì)無(wú)限期的留在內(nèi)存中,減少數(shù)據(jù)丟失的風(fēng)險(xiǎn)。
當(dāng)用戶進(jìn)程調(diào)用 sync 和 fsync 系統(tǒng)調(diào)用時(shí)。這是為了給用戶進(jìn)程提供強(qiáng)制回寫的方法,滿足回寫要求嚴(yán)格的使用場(chǎng)景。
回寫線程的實(shí)現(xiàn)
名稱版本說(shuō)明 bdflush2.6 版本以前 bdflush 內(nèi)核線程在后臺(tái)運(yùn)行,系統(tǒng)中只有一個(gè) bdflush 線程,當(dāng)內(nèi)存消耗到特定閥值以下時(shí),bdflush 線程被喚醒。kupdated 周期性的運(yùn)行,寫回臟頁(yè)。但是整個(gè)系統(tǒng)僅僅只有一個(gè) bdflush 線程,當(dāng)系統(tǒng)回寫任務(wù)較重時(shí),bdflush 線程可能會(huì)阻塞在某個(gè)磁盤的 I / O 上,導(dǎo)致其他磁盤的 I / O 回寫操作不能及時(shí)執(zhí)行。pdflush2.6 版本引入 pdflush 線程數(shù)目是動(dòng)態(tài)的,取決于系統(tǒng)的 I / O 負(fù)載。它是面向系統(tǒng)中所有磁盤的全局任務(wù)的。但是由于 pdflush 是面向所有磁盤的,所以有可能出現(xiàn)多個(gè) pdflush 線程全部阻塞在某個(gè)擁塞的磁盤上,同樣導(dǎo)致其他磁盤的 I / O 回寫不能及時(shí)執(zhí)行。flusher 線程 2.6.32 版本以后引入 flusher 線程的數(shù)目不是唯一的,同時(shí) flusher 線程不是面向所有磁盤的,而是每個(gè) flusher 線程對(duì)應(yīng)一個(gè)磁盤
頁(yè)緩存的回收
Linux 中頁(yè)緩存的替換邏輯是一個(gè)修改過(guò)的 LRU 實(shí)現(xiàn),也稱為雙鏈策略。和以前不同,Linux 維護(hù)的不再是一個(gè) LRU 鏈表,而是維護(hù)兩個(gè)鏈表:活躍鏈表和非活躍鏈表。處于活躍鏈表上的頁(yè)面被認(rèn)為是“熱”的且不會(huì)被換出,而在非活躍鏈表上的頁(yè)面則是可以被換出的。在活躍鏈表中的頁(yè)面必須在其被訪問(wèn)時(shí)就處于非活躍鏈表中。兩個(gè)鏈表都被偽 LRU 規(guī)則維護(hù):頁(yè)面從尾部加入,從頭部移除,如同隊(duì)列。兩個(gè)鏈表需要維持平衡–如果活躍鏈表變得過(guò)多而超過(guò)了非活躍鏈表,那么活躍鏈表的頭頁(yè)面將被重新移回到非活躍鏈表中,一遍能再被回收。雙鏈表策略解決了傳統(tǒng) LRU 算法中對(duì)僅一次訪問(wèn)的窘境。而且也更加簡(jiǎn)單的實(shí)現(xiàn)了偽 LRU 語(yǔ)義。這種雙鏈表方式也稱作 LRU/2。更普遍的是 n 個(gè)鏈表,故稱 LRU/n。
“有哪些 Linux 磁盤緩存相關(guān)知識(shí)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注丸趣 TV 網(wǎng)站,丸趣 TV 小編將為大家輸出更多高質(zhì)量的實(shí)用文章!