摘要:寫緩存與寫磁盤先看下寫文件操作的流程結(jié)構(gòu)圖磁盤緩存是物理內(nèi)存的一部分,專門供操作系統(tǒng)用作讀寫磁盤的緩沖之用。這印證了前面的說法,字符串在文件關(guān)閉前只在磁盤緩存里,還未真正寫到磁盤上,所以讀進(jìn)程無法讀出。
多進(jìn)程讀寫同一個(gè)文件的問題
不考慮文件內(nèi)容的錯(cuò)亂,多進(jìn)程是可以同時(shí)讀寫一個(gè)文件的。當(dāng)一個(gè)進(jìn)程在寫,讀的進(jìn)程能否讀到最新的內(nèi)容,取決于最新的內(nèi)容是否真正寫到了磁盤上。
寫緩存與寫磁盤先看下寫文件操作的流程結(jié)構(gòu)圖:
磁盤緩存是物理內(nèi)存的一部分,專門供操作系統(tǒng)用作讀寫磁盤的緩沖之用。磁盤緩存與“硬盤自帶的緩存”是不一樣的概念,它的大小是可以動(dòng)態(tài)設(shè)置的,而不像硬盤緩存在出廠的時(shí)候固定就是32M或64M。
我們通常用到的寫文件API,其實(shí)是寫到磁盤緩存上,可用python語(yǔ)言做一個(gè)實(shí)驗(yàn):
if opt == "-w": with open("1.txt", "w") as writer: writer.write("hehe ") time.sleep(10) elif opt == "-r": with open("1.txt") as fp: for line in fp: line = line.rstrip() print line
我們?cè)谟?w選項(xiàng)寫hehe之后不會(huì)立刻關(guān)閉文件,而是sleep了10s,方便使用-r選項(xiàng)去讀文件,讀的時(shí)候我們發(fā)現(xiàn),除非文件關(guān)閉,否則讀不出任何內(nèi)容。這印證了前面的說法,hehe字符串在文件關(guān)閉前只在磁盤緩存里,還未真正寫到磁盤上,所以讀進(jìn)程無法讀出。
如何確保寫到磁盤上而不只是磁盤緩存里呢?python文檔給出了建議:
file.flush() Flush the internal buffer. Note flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
文檔建議我們flush+fsync,確保內(nèi)容確實(shí)更新到了磁盤。
fsync的幫助也指出了這一點(diǎn):
os.fsync(fd) Force write of file with filedescriptor fd to disk. On Unix, this calls the native fsync() function; on Windows, the MS _commit() function. If you’re starting with a Python file object f, first do f.flush(), and then do os.fsync(f.fileno()), to ensure that all internal buffers associated with f are written to disk.
所謂的“內(nèi)部緩存”就是磁盤緩存,強(qiáng)制更新到磁盤,linux下用的是大家熟知的fsync,windows下則是_commit函數(shù)。
我們將寫的代碼改成:
if opt == "-w": with open("1.txt", "w") as writer: writer.write("hehe ") writer.flush() os.fsync(writer.fileno()) time.sleep(10)
果然,讀進(jìn)程就能在文件尚未關(guān)閉時(shí)讀到hehe字符串了。
但是,fsync是要慎用的,因?yàn)槊織l內(nèi)容都強(qiáng)制刷新到磁盤,雖然非??煽?,卻會(huì)帶來性能的急劇下降,我們可以在上述例子的基礎(chǔ)上改成寫10萬條字符串,對(duì)比“普通寫”與“fsync寫”的效率,會(huì)發(fā)現(xiàn)后者的耗時(shí)是前者的數(shù)千倍甚至是上萬倍!這也正是redis的AOF日志雖然提供了fsync級(jí)別的磁盤同步卻不建議我們使用的原因(也因此redis的日志做不到絕對(duì)的單點(diǎn)可靠)。
這里還有一個(gè)疑問,按python的文檔,flush并不一定能將最新的內(nèi)容更新到磁盤上,我們查看java file API的文檔,發(fā)現(xiàn)也有類似的說法。這是為何?我個(gè)人的猜測(cè),flush只是簡(jiǎn)單的把磁盤緩存的內(nèi)容放到磁盤驅(qū)動(dòng)程序的寫請(qǐng)求隊(duì)列里就返回,本質(zhì)上是異步的,而fsync除了放內(nèi)容到寫請(qǐng)求隊(duì)列還會(huì)等待磁盤驅(qū)動(dòng)程序的返回結(jié)果,本質(zhì)上是同步的。由于fsync還要額外經(jīng)歷:等待寫請(qǐng)求到隊(duì)列首部+磁盤驅(qū)動(dòng)程序調(diào)用磁盤控制器+磁盤控制器寫到物理磁盤等步驟,自然就拖慢了fsync的速度。
進(jìn)程內(nèi)緩存與磁盤緩存進(jìn)程內(nèi)緩存指的是我在寫磁盤緩存前,在自己的程序里再做一個(gè)緩存,將多條消息累積到一定的大小,再一次提交給磁盤緩存,這樣能提升寫的效率。java里一般要在FileWriter之上再套一層BufferedWriter寫入,就是這個(gè)用途,實(shí)測(cè)下來,也能有一倍的效率提升。
python語(yǔ)言里沒有BufferedWriter,對(duì)于10萬條字符串的寫可以考慮別的方法,比如我們可以每500條拼成一個(gè)大的字符串再做寫入,實(shí)測(cè)也有一倍的效率提升。
不過,如同前面的“普通寫”與“fsync寫”一樣,效率的提升不是全無代價(jià),它往往伴隨著可靠性的降低。進(jìn)程內(nèi)緩存是屬于某個(gè)進(jìn)程的,一旦該進(jìn)程突然core掉,進(jìn)程內(nèi)緩存就會(huì)丟失,從用戶層面看來,就是我明明已經(jīng)write好了的數(shù)據(jù),很可能并未寫到磁盤里。相比之下,磁盤緩存就更可靠一些,因?yàn)樗怯刹僮飨到y(tǒng)管理的,與進(jìn)程無關(guān),除非是機(jī)器斷電,否則它不會(huì)丟失數(shù)據(jù),也就是說,即使我的進(jìn)程core掉,之前write的內(nèi)容依然可以安全到達(dá)磁盤上。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/61906.html
摘要:寫緩存與寫磁盤先看下寫文件操作的流程結(jié)構(gòu)圖磁盤緩存是物理內(nèi)存的一部分,專門供操作系統(tǒng)用作讀寫磁盤的緩沖之用。這印證了前面的說法,字符串在文件關(guān)閉前只在磁盤緩存里,還未真正寫到磁盤上,所以讀進(jìn)程無法讀出。 多進(jìn)程讀寫同一個(gè)文件的問題 不考慮文件內(nèi)容的錯(cuò)亂,多進(jìn)程是可以同時(shí)讀寫一個(gè)文件的。當(dāng)一個(gè)進(jìn)程在寫,讀的進(jìn)程能否讀到最新的內(nèi)容,取決于最新的內(nèi)容是否真正寫到了磁盤上。 寫緩存與寫磁盤 先...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。寫一個(gè)符合規(guī)范并可配合使用的寫一個(gè)符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個(gè)需求:在系統(tǒng)初始化時(shí)通過http獲取一個(gè)第三方服務(wù)器端的列表,第三方服務(wù)器提供了一個(gè)接口,可通過...
摘要:的翻譯文檔由的維護(hù)很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會(huì)promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:可以通過大數(shù)據(jù)生態(tài)的一系列工具生態(tài)來解決大數(shù)據(jù)問題數(shù)據(jù)分片主要有兩種方式哈希和范圍。哈希的問題是范圍查詢支持不佳,范圍的問題是可能冷熱數(shù)據(jù)不均。 后端好書閱讀與推薦系列文章:后端好書閱讀與推薦后端好書閱讀與推薦(續(xù))后端好書閱讀與推薦(續(xù)二)后端好書閱讀與推薦(續(xù)三)后端好書閱讀與推薦(續(xù)四)后端好書閱讀與推薦(續(xù)五)后端好書閱讀與推薦(續(xù)六) Elasticsearch權(quán)威指南 El...
摘要:可以通過大數(shù)據(jù)生態(tài)的一系列工具生態(tài)來解決大數(shù)據(jù)問題數(shù)據(jù)分片主要有兩種方式哈希和范圍。哈希的問題是范圍查詢支持不佳,范圍的問題是可能冷熱數(shù)據(jù)不均。 后端好書閱讀與推薦系列文章:后端好書閱讀與推薦后端好書閱讀與推薦(續(xù))后端好書閱讀與推薦(續(xù)二)后端好書閱讀與推薦(續(xù)三)后端好書閱讀與推薦(續(xù)四)后端好書閱讀與推薦(續(xù)五)后端好書閱讀與推薦(續(xù)六) Elasticsearch權(quán)威指南 El...
閱讀 1363·2023-04-26 00:10
閱讀 2461·2021-09-22 15:38
閱讀 3937·2021-09-22 15:13
閱讀 3552·2019-08-30 13:11
閱讀 672·2019-08-30 11:01
閱讀 3069·2019-08-29 14:20
閱讀 3236·2019-08-29 13:27
閱讀 1753·2019-08-29 11:33