1. 如何做到 0.2 秒復(fù)制 100G 文件?

        共 4191字,需瀏覽 9分鐘

         ·

        2022-05-18 19:48



        cp 引發(fā)的思考


        今天同事用 cp 命令,把他給驚到了!

        背景是這樣的:他用 cp 拷貝了一個 100 G 的文件,竟然一秒不到就拷貝完成了!

        用 ls 看一把文件,顯示文件確實(shí)是 100 G。

        sh-4.4#?ls?-lh??
        -rw-r--r--?1?root?root?100G?Mar??6?12:22?test.txt

        但是 copy 起來為什么會這么快呢?

        sh-4.4#?time?cp?./test.txt?./test.txt.cp??
        ??
        real?0m0.107s??
        user?0m0.008s??
        sys?0m0.085s

        一個 SATA 機(jī)械盤的寫能力能到 150 M/s (大部分的機(jī)械盤都是到不了這個值的)就算非常不錯了,正常情況下,copy 一個 100G 的文件至少要 682 秒(100 G/ 150 M/s),也就是 11 分鐘。

        實(shí)際情況卻是 cp 一秒沒到就完成了工作,驚呆了,為啥呢?

        更詭異的是:他的文件系統(tǒng)只有 40 G,為啥里面會有一個 100 G的文件呢?

        同事把我找來,看看這個詭異的問題。

        分析文件

        我讓他先用 du 命令看一下,卻只有 2M ,根本不是 100G,這是怎么回事?

        sh-4.4#?du?-sh?./test.txt??
        2.0M?./test.txt

        再看 stat 命令顯示的信息:

        sh-4.4#?stat?./test.txt??
        ??File:?./test.txt??
        ??Size:?107374182400?Blocks:?4096???????IO?Block:?4096???regular?file??
        Device:?78h/120d?Inode:?3148347?????Links:?1??
        Access:?(0644/-rw-r--r--)??Uid:?(????0/????root)???Gid:?(????0/????root)??
        Access:?2021-03-13?12:22:00.888871000?+0000??
        Modify:?2021-03-13?12:22:46.562243000?+0000??
        Change:?2021-03-13?12:22:46.562243000?+0000??
        ?Birth:?-

        stat 命令輸出解釋:

        • Size 為 107374182400(知識點(diǎn):單位是字節(jié)),也就是 100G;

        • Blocks 這個指標(biāo)顯示為 4096(知識點(diǎn):一個 Block 的單位固定是 512 字節(jié),也就是一個扇區(qū)的大?。?,這里表示為 2M。


        劃重點(diǎn):

        • Size 表示的是文件大小,這個也是大多數(shù)人看到的大??;

        • Blocks 表示的是物理實(shí)際占用空間。


        同事問道:“文件大小和實(shí)際物理占用,這兩個竟然不是相同的概念 !為什么是這樣?”

        “看來,我們必須得深入文件系統(tǒng)才能理解了,來,我給你好好講講?!?/section>


        文件系統(tǒng)


        文件系統(tǒng)聽起來很高大上,通俗話就用來存數(shù)據(jù)的一個容器而已,本質(zhì)和你的行李箱、倉庫沒有啥區(qū)別,只不過文件系統(tǒng)存儲的是數(shù)字產(chǎn)品而已。

        我有一個視頻文件,我把這個視頻放到這個文件系統(tǒng)里,下次來拿,要能拿到我完整的視頻文件數(shù)據(jù),這就是文件系統(tǒng),對外提供的就是存取服務(wù)。

        現(xiàn)實(shí)的存取場景

        例如你到火車站使用寄存服務(wù):

        存行李的時候,是不是要登記一些個人信息?對吧,至少自己名字要寫上。可能還會給你一個牌子,讓你掛手上,這個東西就是為了標(biāo)示每一個唯一的行李。

        取行李的時候,要報自己名字,有牌子的給他牌子,然后工作人員才能去特定的位置找到你的行李。

        劃重點(diǎn):存的時候必須記錄一些關(guān)鍵信息(記錄 ID、給身份牌),取的時候才能正確定位到。

        文件系統(tǒng)

        回到我們的文件系統(tǒng),對比上面的行李存取行為,可以做個簡單的類比。

        • 登記名字就是在文件系統(tǒng)記錄文件名;

        • 生成的牌子就是元數(shù)據(jù)索引;

        • 你的行李就是文件;

        • 寄存室就是磁盤(容納東西的物理空間);

        • 管理員整套運(yùn)行機(jī)制就是文件系統(tǒng)。


        上面的對應(yīng)并不是非常嚴(yán)謹(jǐn),僅僅是幫助大家理解文件系統(tǒng)而已,讓大家知道其實(shí)文件系統(tǒng)是非常樸實(shí)的一個東西,思想都來源于生活。

        空間管理

        現(xiàn)在思考文件系統(tǒng)是怎么管理空間的?

        如果,一個連續(xù)的大磁盤空間給你使用,你會怎么使用這段空間呢?

        直觀的一個想法,我把進(jìn)來的數(shù)據(jù)就完整的放進(jìn)去。


        這種方式非常容易實(shí)現(xiàn),屬于眼前最簡單,以后最麻煩的方式。因?yàn)闀斐珊芏嗫斩?,明明還有很多空間位置,但是由于整個太大,形狀不合適(數(shù)據(jù)大?。睦锒挤挪幌?。因?yàn)槟阋乓粋€完整的空間。

        怎么改進(jìn)?有人會想,既然整個放不進(jìn)去,那就剁碎了唄。這里塞一點(diǎn),那里塞一點(diǎn),就塞進(jìn)去了。

        對,思路完全正確。改進(jìn)的方式就是切分,把空間按照一定粒度切分。每個小粒度的物理塊命名為 Block,每個 Block 一般是 4K 大小,用戶數(shù)據(jù)存到文件系統(tǒng)里來自然也是要切分,存儲到磁盤上各個角落。


        圖示標(biāo)號表示這個完整對象的 Block 的序號,用來復(fù)原對象用的。

        隨之而來又有一個問題:你光會切成塊還不行,取文件數(shù)據(jù)的時候,還得把它們給組合起來才行。

        所以,要有一個表記錄文件對應(yīng)所有 Block 的位置,這個表被文件系統(tǒng)稱為inode。

        寫文件的流程是這樣的:

        • 先寫數(shù)據(jù):數(shù)據(jù)先按照 Block 粒度存儲到磁盤的各個位置;

        • 再寫元數(shù)據(jù):然后把 Block 所在的各個位置保存起來,即inode(我用一本書來表示)。



        讀文件流程則是:

        • 先讀inode,找到各個 Block 的位置;

        • 然后讀數(shù)據(jù),構(gòu)造一個完整的文件,給到用戶。



        inode/block 概念

        好,我們現(xiàn)在來看看inode,直觀地感受一下:


        這個 inode 有文件元數(shù)據(jù)和 Block 數(shù)組(長度是 15),數(shù)組中前兩項指向 Block 3 和 Block 11,表示數(shù)據(jù)在這兩個塊中存著。

        你肯定會意識到:Block 數(shù)組只有 15 個元素,每個 Block 是 4K, 難道一個文件最大只能是 15 * 4K = 60 K?

        這是絕對不行的!

        最簡單的辦法就是:把這個 Block 數(shù)組長度給擴(kuò)大!

        比如我們想讓文件系統(tǒng)最大支持 100G 的文件,Block 數(shù)組需要這么長:

        (10010241024)/4 = 26214400

        Block 數(shù)組中每一項是 4 個字節(jié),那就需要 (26214400*4)/1024/1024 = 100M。

        為了支持 100G 的文件,我們的 Block 數(shù)組本身就得 100M !

        并且對每個文件都是如此 !即使這個文件只有 1K!?這將是巨大浪費(fèi)!

        肯定不能這么干,解決方案就是間接索引,按照約定,把這 15 個槽位分作 4 個不同類別來用:

        1. 前 12 個槽位(也就是 0 - 11 )我們成為直接索引;

        2. 第 13 個位置,我們稱為 1 級索引;

        3. 第 14 個位置,我們稱為 2 級索引;

        4. 第 15 個位置,我們稱為 3 級索引。



        直接索引:能存 12 個 block 編號,每個 block 4K,就是 48K,也就是說,48K 以內(nèi)的文件,前 12 個槽位存儲編號就能完全 hold 住。

        一級索引:也就是說這里存儲的編號指向的 block 里面存儲的也是 block 編號,里面的編號指向用戶數(shù)據(jù)。一個 block 4K,每個元素 4 字節(jié),也就是有 1024 個編號位置可以存儲。

        所以,一級索引能尋址 4M(1024 * 4K)空間。


        二級索引:二級索引是在一級索引的基礎(chǔ)上多了一級而已,換算下來,有了 4M 的空間用來存儲用戶數(shù)據(jù)的編號。所以二級索引能尋址 4G(4M/4 * 4K)的空間。


        三級索引:三級索引是在二級索引的基礎(chǔ)上又多了一級,也就是說,有了 4G 的空間來存儲用戶數(shù)據(jù)的 block 編號。所以二級索引能尋址 4T(4G/4 * 4K)的空間。


        所以,在這種文件系統(tǒng)(如ext2)上,通過這種間接塊索引的方式,最大能支撐的文件大小 = 48K + 4M + 4G + 4T ,約等于 4 T。

        這種多級索引尋址性能表現(xiàn)怎么樣?

        在不超過 12 個數(shù)據(jù)塊的小文件的尋址是最快的,訪問文件中的任意數(shù)據(jù)理論只需要兩次讀盤,一次讀 inode,一次讀數(shù)據(jù)塊。

        訪問大文件中的數(shù)據(jù)則需要最多五次讀盤操作:inode、一級間接尋址塊、二級間接尋址塊、三級間接尋址塊、數(shù)據(jù)塊。

        為什么 cp 那么快?

        接下來我們要寫入一個奇怪的文件,這個文件很大,但是真正的數(shù)據(jù)只有 8K:

        在 [0 , 4K] 這位置有 4K 的數(shù)據(jù)。

        在 [1T , 1T+4K] 處也有4K數(shù)據(jù)。

        中間沒有數(shù)據(jù),這樣的文件該如何寫入硬盤?

        1. 創(chuàng)建一個文件,這個時候分配一個 inode;

        2. 在 [0 , 4K] 的位置寫入 4K 數(shù)據(jù),這個時候只需要 一個 block,把這個編號寫到 block[0]?這個位置保存起來;

        3. 在 [1T , 1T+4K] 的位置寫入 4K 數(shù)據(jù),這個時候需要分配一個 block,因?yàn)檫@個位置已經(jīng)落到三級索引才能表現(xiàn)的空間了,所以需要還需要分配出 3 個索引塊;

        4. 寫入完成,close 文件。


        實(shí)際存儲如圖:


        這個時候,我們的文件看起來是超大文件,size 等于 1T + 4K ,但里面實(shí)際的數(shù)據(jù)只有 8K,位置分別是 [0 , 4K ] ,[1T , 1T+4K]。

        由于沒寫數(shù)據(jù)的地方不用分配物理 block 塊,所以實(shí)際占用的物理空間只有 8K。

        重點(diǎn):文件 size 只是 inode 里面的一個屬性,實(shí)際物理空間占用則是要看用戶數(shù)據(jù)放了多少個 block ,沒寫數(shù)據(jù)的地方不用分配物理 block 塊。

        這樣的文件其實(shí)就是稀疏文件, 它的邏輯大小和實(shí)際物理空間是不相等的。

        所以當(dāng)我們用 cp 命令去復(fù)制一個這樣的文件時,那肯定迅速就完成了。

        總結(jié)

        好,我們再深入思考下,文件系統(tǒng)為什么能做到這一點(diǎn)?

        • 首先,最關(guān)鍵的是把磁盤空間切成離散的、定長的 block 來管理;

        • 然后,通過 inode 能查找到所有離散的數(shù)據(jù)(保存了所有的索引);

        • 最后,實(shí)現(xiàn)索引塊和數(shù)據(jù)塊空間的后分配。


        這三點(diǎn)是層層遞進(jìn)的。


        后記


        我把這點(diǎn)小知識給小伙伴講了一小時,看到他感動欲哭的表情,我覺得他學(xué) fei 了,非常滿意。

        是我想太多了嗎?中午吃飯都沒叫我。

        作者:OSC開源社區(qū)

        來源:https://mp.weixin.qq.com/s/GqKHhAd93iQorDeGyHBMnA


        瀏覽 62
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
          
          

            1. 奇米色影女人天堂7777 | 另类专区亚洲 | 九一免费国产 | 96人成网站色www免费 | 在线视频一区少妇露脸福利在线 |