FYI
????????廣義上Cache的同步方式有兩種,即Write Through(寫穿)和Write back(寫回). 從名字上就能看出這兩種方式都是從寫操作的不同處理方式引出的概念(純讀的話就不存在Cache一致性了,不是么)。對應(yīng)到Linux的Page Cache上所謂Write Through就是指write()操作將數(shù)據(jù)拷貝到Page Cache后立即和下層進(jìn)行同步的寫操作,完成下層的更新后才返回。而Write back正好相反,指的是寫完P(guān)age Cache就可以返回了。Page Cache到下層的更新操作是異步進(jìn)行的。
? ??????Linux下Buffered IO默認(rèn)使用的是Write back機(jī)制,即文件操作的寫只寫到Page Cache就返回,之后Page Cache到磁盤的更新操作是異步進(jìn)行的。Page Cache中被修改的內(nèi)存頁稱之為臟頁(Dirty Page),臟頁在特定的時(shí)候被一個(gè)叫做pdflush(Page Dirty Flush)的內(nèi)核線程寫入磁盤,寫入的時(shí)機(jī)和條件如下:
? ??????????????當(dāng)空閑內(nèi)存低于一個(gè)特定的閾值時(shí),內(nèi)核必須將臟頁寫回磁盤,以便釋放內(nèi)存。
????????????????當(dāng)臟頁在內(nèi)存中駐留時(shí)間超過一個(gè)特定的閾值時(shí),內(nèi)核必須將超時(shí)的臟頁寫回磁盤。
????????????????用戶進(jìn)程調(diào)用sync(2)、fsync(2)、fdatasync(2)系統(tǒng)調(diào)用時(shí),內(nèi)核會執(zhí)行相應(yīng)的寫回操作。
? ? ? ? Flush策略由以下幾個(gè)參數(shù)決定(數(shù)值單位均為1/100秒):
????????????????# flush每隔5秒執(zhí)行一次
????????????????root@082caa3dfb1d / $ sysctl vm.dirty_writeback_centisecs
????????????????vm.dirty_writeback_centisecs = 500
????????????????# 內(nèi)存中駐留30秒以上的臟數(shù)據(jù)將由flush在下一次執(zhí)行時(shí)寫入磁盤
????????????????root@082caa3dfb1d / $ sysctl vm.dirty_expire_centisecs
????????????????vm.dirty_expire_centisecs = 3000
????????????????# 若臟頁占總物理內(nèi)存10%以上,則觸發(fā)flush把臟數(shù)據(jù)寫回磁盤
????????????????root@082caa3dfb1d / $ sysctl vm.dirty_background_ratio
????????????????vm.dirty_background_ratio = 10
????????默認(rèn)是寫回方式,如果想指定某個(gè)文件是寫穿方式呢?即寫操作的可靠性壓倒效率的時(shí)候,能否做到呢?當(dāng)然能,除了之前提到的fsync()之類的系統(tǒng)調(diào)用外,在open()打開文件時(shí),傳入O_SYNC這個(gè)flag即可實(shí)現(xiàn)。
????????文件讀寫遭遇斷電時(shí),數(shù)據(jù)還安全嗎?相信你有自己的答案了。使用O_SYNC或者fsync()刷新文件就能保證安全嗎?現(xiàn)代磁盤一般都內(nèi)置了緩存,代碼層面上也只能講數(shù)據(jù)刷新到磁盤的緩存了。當(dāng)數(shù)據(jù)已經(jīng)進(jìn)入到磁盤的高速緩存時(shí)斷電了會怎么樣?這個(gè)恐怕不能一概而論了。不過可以使用hdparm -W0命令關(guān)掉這個(gè)緩存,相應(yīng)的,磁盤性能必然會降低。