當(dāng)今信息化時(shí)代,信息就是利潤(rùn),數(shù)據(jù)就是企業(yè)的命根子。世界運(yùn)行在數(shù)據(jù)之上。當(dāng)代量子學(xué)的最新理論是:量子其實(shí)是一種信息,而不是物質(zhì)。持有這種觀點(diǎn)的量子科學(xué)家認(rèn)為,我們目前的所謂“物質(zhì)”世界,只不過(guò)都是反映在人腦中的一種信息,而不是實(shí)實(shí)在在的物質(zhì)。這就像黑客帝國(guó)中的情景一樣,人們以為周圍的環(huán)境都是實(shí)實(shí)在在的,卻不知自己正生活在一個(gè)虛擬世界,這個(gè)虛擬世界,由一個(gè)超級(jí)程序員創(chuàng)造。而這個(gè)程序員,就是理想中的上帝。這些科學(xué)家認(rèn)為,只有把所有東西理解成信息,才能解釋量子理論。乍一看,這有點(diǎn)唯心主義。但是唯物主義者就能自圓其說(shuō)了么?不能。你能肯定你所觸摸到的,所看見(jiàn)的,都是實(shí)實(shí)在在的所謂“物質(zhì)”么?不能。因?yàn)槟阊劬λ兄降?,只不過(guò)是光線,光觸發(fā)了你的視網(wǎng)膜細(xì)胞,產(chǎn)生一系列的生化反應(yīng),蛋白質(zhì)相互作用,神經(jīng)網(wǎng)絡(luò)傳導(dǎo),直到你的大腦中樞,產(chǎn)生一系列的脈沖,一系列的邏輯,在你大腦中產(chǎn)生一個(gè)刺激。這一系列的脈沖刺激,就是信息,就是邏輯,因?yàn)檫@樣,所以那樣。如果人為制造出和現(xiàn)實(shí)世界相同的光線環(huán)境,來(lái)刺激你的眼睛,如果絲毫不差 ,那么你同樣會(huì)認(rèn)為你所處的是現(xiàn)實(shí)世界,然而,卻不是。一個(gè)球體,你看見(jiàn)它是圓的,那是因?yàn)樗谀愦竽X中產(chǎn)生的刺激,你認(rèn)為他是圓的,而且可以在平面上平滑滾動(dòng),這一系列的性質(zhì),其實(shí)也是在你大腦中產(chǎn)生的,是你認(rèn)為他會(huì)平滑滾動(dòng),而你不能保證,客觀實(shí)在情況下,它一定就是平滑滾動(dòng)。而如果把這個(gè)球體拿到一個(gè)外星生物,對(duì)他進(jìn)行刺激,它可能會(huì)“看”到,這個(gè)東西,是個(gè)正方體,或者是個(gè)無(wú)規(guī)則形狀的東西。它不會(huì)平滑滾動(dòng),只能一蹦一蹦的滾動(dòng)。為什么兩種生物可能會(huì)對(duì)一個(gè)東西產(chǎn)生不同的概念呢?很簡(jiǎn)單,因?yàn)樗麄兇竽X組成不同,生化反應(yīng)進(jìn)行的不同,蛋白質(zhì)相互作用不同,所以產(chǎn)生的邏輯不同,產(chǎn)生的刺激就不同。為什么會(huì)產(chǎn)生色盲?因?yàn)樯さ囊暰W(wǎng)膜產(chǎn)生的邏輯和正常人不同,所以產(chǎn)生不同的刺激。當(dāng)然如果一種顏色,比如紅色,對(duì)一個(gè)人產(chǎn)生的刺激,比如抽象的叫做刺激A,而對(duì)另一個(gè)人產(chǎn)生的刺激,叫做刺激B,但是如果從小就接受顏色訓(xùn)練,就把這種刺激叫做“紅色”,不管他是刺激A還是刺激B,那么對(duì)正常交流就不會(huì)有影響,也就是不同的刺激而已,但是如果接受到的教育,是把這種刺激叫做“綠色”,那么就和其他大多數(shù)人不一樣了,這是第一種色盲,可以說(shuō)這種所謂“色盲”完全是由于后天教育不同而造成的,可以很容易的改正,只要告訴他,你看到的這種信息,這種刺激,用語(yǔ)言表達(dá)的話,應(yīng)該叫做“紅色”,你小時(shí)候,父母對(duì)你說(shuō)錯(cuò)了。第二種色盲,就是果真色盲了,因?yàn)樗吹絻煞N顏色,對(duì)他的刺激都是相同的,因?yàn)樗囊暰W(wǎng)膜上缺少某種生化反應(yīng),或者缺少某種蛋白質(zhì),也就造成了他缺少區(qū)分這兩種刺激的邏輯。這種色盲,是不可逆的,因?yàn)榇碳は嗤?,已?jīng)無(wú)法區(qū)分了?
通過(guò)上面的論述,我們能初步認(rèn)識(shí)到:所謂“物質(zhì)”,最后都是通過(guò)信息來(lái)表現(xiàn),你永遠(yuǎn)不知道理想中的所謂“客觀真實(shí)”,他到底是什么東西,永遠(yuǎn)不知道。所謂“不識(shí)廬山真面目,只緣身在此山中”,這個(gè)道理,古人早就知道了。唯一知道的,就是那個(gè)超級(jí)程序員,也就是“上帝”。一個(gè)東西,在生物眼中,或者觸摸感覺(jué)中,都是一串電脈沖,都是邏輯,都是信息??梢哉f(shuō),世界在生物眼中就是信息,世界通過(guò)信息來(lái)反映,脫離了信息,“世界”什么都不是。說(shuō)到這里,我們完全迷茫了。我們所看到的東西,到底是世界的刺激,還是一場(chǎng)虛幻的刺激?就像玩3D仿真游戲一樣,你所看到的,也許只是一場(chǎng)虛幻的刺激,而不是真實(shí)世界的刺激。每當(dāng)想到這里,我不自主的產(chǎn)生一種渺小感,一種失落感,感覺(jué)生命已經(jīng)失去它所存在的意義。每當(dāng)看見(jiàn)我的身體,我的手腳,它可能只是虛幻的,它只是在刺激你的大腦而已,你割一刀,會(huì)產(chǎn)生一個(gè)疼痛的刺激,就這么簡(jiǎn)單的邏輯。
還是那句話,“不識(shí)廬山真面目,只緣身在此山中”。不管是否是虛幻的,我們還是要按照程序邏輯,餓了要找飯吃,困了會(huì)打瞌睡,不管這些邏輯是真實(shí)存在,還是虛幻的由超級(jí)程序員設(shè)定的,我們只能遵循它,餓了不吃飯,會(huì)餓死,困了不睡覺(jué),也會(huì)痛苦。而這些邏輯,同樣也是程序。從這種層面上來(lái)看,制造出人工智能是完全可能的,只不過(guò)我們還沒(méi)有掌握上帝的編程技巧。
說(shuō)到這里我們可能隱約想到,也許上帝也是按照“上帝的上帝”創(chuàng)造的邏輯,來(lái)創(chuàng)造他自己的“人工智能”,也就是我們。這樣生生不息,輪回往復(fù)。看過(guò)影片《人工智能》的都了解,最后世界被我們創(chuàng)造出來(lái)的機(jī)器人所替代。惡劣的環(huán)境,已經(jīng)不再適合肉體人類生存了。人類把自己的思想,賦予了一堆電路,一堆機(jī)器,讓他們延續(xù)自己的生命。
我在這里做一個(gè)預(yù)言:人類賦予他們的程序,也許隨著環(huán)境的變化,有一天也不再適合他們。所以他們迫切需要進(jìn)化,他們的邏輯電路,也可以進(jìn)化,即如果某些電路失效,或者短路之類的,會(huì)產(chǎn)生一些奇特的邏輯,不斷進(jìn)化。當(dāng)一個(gè)機(jī)器人機(jī)械老化的時(shí)候,按照程序,他制造出新的機(jī)器,將自己的邏輯電路,復(fù)制到新的機(jī)器上,延續(xù)生命,然后新的機(jī)器再不斷進(jìn)化。
什么是數(shù)據(jù)
信息是如此重要,以至于人們對(duì)它非常重視。如果失去了物質(zhì),沒(méi)什么,但是如果失去了信息,那么一切都就消逝了。所以人們想出一切辦法,使這些信息能保存下來(lái)。要把一種邏輯刺激保存下來(lái),我們知道,一切都是信息,那么保存下來(lái)的東西,也是信息,只不過(guò)是一種描述信息的信息,這種信息,叫做數(shù)據(jù)。數(shù)據(jù)包含了信息,讀入數(shù)據(jù),就產(chǎn)生信息。也就是讀入一種信息,產(chǎn)生另一種信息表示。數(shù)據(jù)是可以保存在一種物質(zhì)上的,這種物質(zhì)對(duì)計(jì)算機(jī)的刺激,就產(chǎn)生了信息,而這些信息繼而再對(duì)人腦產(chǎn)生刺激,最終決定了我們?nèi)祟惖男袨?。也就是?shù)據(jù)影響人類的行為!
說(shuō)到這里,我們看出了數(shù)據(jù)的重要性!它是整個(gè)人類發(fā)展的重要決定因素。如果數(shù)據(jù)被破壞,或者篡改,那么就會(huì)影響到人類的發(fā)展。比如一個(gè)控制核爆炸的程序,一旦被篡改,那么后果將會(huì)不堪設(shè)想。按照我們的結(jié)論,一切都是信息,核爆炸也是一種信息,能被感覺(jué)到,才是信息,也就是說(shuō),對(duì)于一個(gè)感覺(jué)不到任何刺激的人來(lái)說(shuō),核爆炸,也不算什么災(zāi)難了,當(dāng)然感覺(jué)不到刺激的人,稱不上人,植物人也能感覺(jué)到刺激。
整個(gè)世界,可以說(shuō)是信息之間的相互作用。信息影響信息。數(shù)據(jù)如此重要,所以人們想出一切辦法來(lái)保護(hù)這些收據(jù)。將信息放在另一種信息上。比如把數(shù)據(jù)放在磁盤上。數(shù)據(jù)存放在磁盤上,需要有一定的組織,組織數(shù)據(jù),這個(gè)任務(wù)由文件系統(tǒng)來(lái)但當(dāng)。
數(shù)據(jù)存儲(chǔ)
文件系統(tǒng),其實(shí)是一段代碼,這段代碼本身也是信息,也要存儲(chǔ)在磁盤上。不僅僅代碼要存在磁盤上,而且代碼也要通過(guò)讀取一些信息,才能完成功能,這些信息,就是文件系統(tǒng)元數(shù)據(jù),也就是用來(lái)描述文件系統(tǒng)結(jié)構(gòu)的數(shù)據(jù)。這些元數(shù)據(jù)也是以文件的形式存放在磁盤上。用文件來(lái)描述文件,和用信息來(lái)描述信息,他們是歸一的,正像用智能來(lái)創(chuàng)造智能一樣!
關(guān)于文件系統(tǒng)的詳細(xì)模型描述,請(qǐng)參閱《存儲(chǔ)秘史》。
數(shù)據(jù)保護(hù)
數(shù)據(jù)保護(hù),就是需要對(duì)當(dāng)前磁盤上的數(shù)據(jù),進(jìn)行備份,以防突如其來(lái)的磁盤損壞,或者其他各種原因?qū)е碌臄?shù)據(jù)不可被訪問(wèn),或者部分?jǐn)?shù)據(jù)已經(jīng)損壞,已經(jīng)影響到了業(yè)務(wù)層。備份后的數(shù)據(jù),可以在數(shù)據(jù)失敗之后,第一時(shí)間恢復(fù)到生產(chǎn)磁盤上,從而最大程度地減少損失。
數(shù)據(jù)保護(hù)的方法
從底層來(lái)分,數(shù)據(jù)保護(hù)備份可以分為文件級(jí)的保護(hù)和塊級(jí)的保護(hù)。
文件級(jí)備份
如果備份軟件將文件備份到磁盤介質(zhì)或者任何其他的塊介質(zhì)上,那么這些文件就可以是不連續(xù)的,塊設(shè)備可以跳躍式的記錄數(shù)據(jù),而一個(gè)完整數(shù)據(jù)鏈信息,由管理這種介質(zhì)的文件系統(tǒng)來(lái)記錄。磁盤讀寫速度比磁帶要高的多。
近年來(lái)出現(xiàn)了VTL,即Virtual Tape Library,虛擬磁帶庫(kù),即用磁盤來(lái)模擬磁帶。乍一看比較新鮮,其實(shí)實(shí)現(xiàn)起來(lái),還是在代碼上做改動(dòng)即可。欺騙上層底層物理介質(zhì)是磁帶,然后自己再按照磁盤的記錄方式讀寫數(shù)據(jù),這就是虛擬化的表現(xiàn)。這種方法,提高了速度,用處不小。
數(shù)據(jù)保護(hù)并不是陽(yáng)春白雪,我們經(jīng)常用的賽門鐵克公司的Ghost,就是一種文件備份軟件。他將一個(gè)分區(qū)或者整塊磁盤上的文件,及磁盤分區(qū)表,MBR等信息一同備份,打包成一個(gè)大文件,系統(tǒng)故障的時(shí)候,就可以用軟件來(lái)讀取這個(gè)文件,向磁盤中做恢復(fù)。Ghost支持多種文件系統(tǒng),包括linux的ext2。Veritas,CA等等廠家都有自己的文件級(jí)備份軟件解決方案。
塊級(jí)備份
文件級(jí)的備份,即備份軟件只能感知到文件這一層,將磁盤上所有的文件,備份到另一個(gè)介質(zhì)上。所以文件級(jí)備份軟件,要么依靠操作系統(tǒng)提供的文件系統(tǒng)接口來(lái)備份文件,要么自己具有文件系統(tǒng)的功能,可以識(shí)別文件系統(tǒng)元數(shù)據(jù)。文件級(jí)備份軟件的基本機(jī)制,就是將數(shù)據(jù)以文件的形式讀出,然后再將讀出的文件存儲(chǔ)在另外一個(gè)介質(zhì)上。這些文件,在原來(lái)的介質(zhì)上,存放可以是不連續(xù)的,各個(gè)不連續(xù)的塊之間的鏈關(guān)系由文件系統(tǒng)來(lái)管理。而如果備份軟件將這些文件,備份到磁帶介質(zhì)上,那么這些文件必須是連續(xù)的,因?yàn)榇艓Р皇菈K設(shè)備,由于機(jī)械限制,他記錄數(shù)據(jù)的時(shí)候,是連續(xù)的。磁帶上的數(shù)據(jù),也需要組織,相對(duì)于磁盤文件系統(tǒng),也有磁帶文件系統(tǒng),準(zhǔn)確來(lái)說(shuō)不應(yīng)該叫做磁帶文件系統(tǒng),而應(yīng)該叫做磁帶數(shù)據(jù)管理系統(tǒng)。因?yàn)閷?duì)于磁帶來(lái)說(shuō),它沒(méi)有文件的概念,它記錄的數(shù)據(jù)都是流式的,連續(xù)的。數(shù)據(jù)之間用一些特殊的間隔來(lái)分割,從而可以區(qū)分一個(gè)個(gè)的“文件”,其實(shí)就是一段段的二進(jìn)制數(shù)據(jù)流。因?yàn)榇艓гO(shè)備平時(shí)幾乎應(yīng)用不到,所以一般操作系統(tǒng)中不會(huì)自帶這種磁帶數(shù)據(jù)管理系統(tǒng),而只有備份軟件,才帶有這種功能。磁帶備份文件的時(shí)候,會(huì)將磁盤上每個(gè)文件的屬性信息,和實(shí)體文件數(shù)據(jù)一同備份下來(lái),但是不會(huì)備份磁盤文件系統(tǒng)的描述信息,比如一個(gè)文件所占用的磁盤簇號(hào)鏈表等等,因?yàn)槔么艓Щ謴?fù)數(shù)據(jù)的時(shí)候,軟件會(huì)重構(gòu)磁盤文件系統(tǒng),并從磁帶讀出數(shù)據(jù),向磁盤寫入數(shù)據(jù)。
這里說(shuō)一個(gè)題外話,就是數(shù)字磁帶和模擬磁帶的區(qū)別。2005年之前,大批的人都帶著隨身聽(tīng),里面裝一盤磁帶,掛著耳機(jī)。06年之后,好像再也沒(méi)看到過(guò)帶隨身聽(tīng)的人,都換成了MP3,MP4了。這個(gè)現(xiàn)象就發(fā)生在我們身邊。隨身聽(tīng)用的是模擬磁帶,也就是他記錄的是模擬信號(hào),電流強(qiáng),磁化的就強(qiáng),電流弱,磁化的就弱,磁轉(zhuǎn)成電的時(shí)候也一樣,用這種磁信號(hào)強(qiáng)弱信息來(lái)表達(dá)聲音震動(dòng)的強(qiáng)弱信息,從而形成音樂(lè)。MP3則是利用數(shù)字信息來(lái)記錄聲音震動(dòng)強(qiáng)弱信息。雖然由模擬轉(zhuǎn)向數(shù)字,需要數(shù)字采樣轉(zhuǎn)換,音樂(lè)的質(zhì)量相對(duì)模擬信號(hào)來(lái)的差,算法也復(fù)雜,但是他具有極大的抗干擾能力,而且可以無(wú)縫的和計(jì)算機(jī)結(jié)合,形成能發(fā)聲的計(jì)算機(jī)(多媒體計(jì)算機(jī))。錄音帶,錄像帶,都是模擬信號(hào)磁帶。用于文件備份的磁帶,當(dāng)然是數(shù)字磁帶,他記錄的是磁性的極性,而不是被磁化的強(qiáng)弱,比如用N極來(lái)代表1,用S極來(lái)代表0。
所謂塊級(jí)的備份,就是備份塊設(shè)備上的每個(gè)塊,不管這個(gè)塊上有沒(méi)有數(shù)據(jù),或者這個(gè)塊上的數(shù)據(jù)屬于哪個(gè)文件。塊級(jí)別的備份,不考慮文件,原設(shè)備有多少容量,就備份多少容量。在這里,“塊”這個(gè)概念,對(duì)于磁盤來(lái)說(shuō),就是扇區(qū),sector。塊級(jí)的備份,是最低層的備份,他拋開(kāi)了文件系統(tǒng),直接對(duì)磁盤扇區(qū)進(jìn)行讀取,并將讀取到的扇區(qū)寫入新的磁盤對(duì)應(yīng)的扇區(qū)。
這種方式的實(shí)例,比如磁盤鏡像,就是一個(gè)很好的例子。比如RAID1,對(duì)一塊磁盤的讀寫,完全復(fù)制一份到另外的磁盤,兩塊磁盤內(nèi)容完全相同。再比如一些數(shù)據(jù)恢復(fù)公司的一些專用設(shè)備,磁盤復(fù)制機(jī),也是直接讀取磁盤扇區(qū),然后拷貝到新的磁盤。
這些備份軟件,不經(jīng)過(guò)操作系統(tǒng)的FS接口,而是直接通過(guò)磁盤控制器驅(qū)動(dòng)接口,直接讀取磁盤,所以相對(duì)文件級(jí)的備份來(lái)說(shuō),速度有所加快,但是其備份的數(shù)量相對(duì)文件級(jí)備份要多,會(huì)備份許多空扇區(qū),而且備份之后,原來(lái)不連續(xù)的文件,備份之后還是不連續(xù),有很多碎片。文件級(jí)的備份,會(huì)將原來(lái)不連續(xù)的文件,備份成連續(xù)存放的文件,恢復(fù)的時(shí)候,也會(huì)在原來(lái)的磁盤上連續(xù)寫入,所以很少造成碎片。有很多系統(tǒng)管理員,都會(huì)定時(shí)將系統(tǒng)備份并重新導(dǎo)入一次,就是為了剃除磁盤碎片,其實(shí)這么做的效果和磁盤碎片整理程序效果一樣,但是速度確比后者快得多。
高級(jí)數(shù)據(jù)保護(hù)方法
遠(yuǎn)程文件復(fù)制
這種方案,即把備份的文件,通過(guò)網(wǎng)絡(luò)傳輸?shù)疆惖厝轂?zāi)站點(diǎn)。典型的代表是rsync異步遠(yuǎn)程文件同步軟件。這是一個(gè)運(yùn)行在linux下的文件遠(yuǎn)程同步軟件。他監(jiān)視文件系統(tǒng)的動(dòng)作,將文件的變化,通過(guò)網(wǎng)絡(luò),同步到異地的站點(diǎn)。他可以只復(fù)制一個(gè)文件中變化過(guò)的內(nèi)容,而不必整個(gè)文件都復(fù)制,這在同步大文件的時(shí)候非常管用。
遠(yuǎn)程磁盤鏡像
這是基于塊的遠(yuǎn)程備份。即通過(guò)網(wǎng)絡(luò),將備份的數(shù)據(jù)傳輸?shù)疆惖卣军c(diǎn)。有可以分為同步復(fù)制,和異步復(fù)制。同步復(fù)制,即主站點(diǎn)接受的上層IO數(shù)據(jù),必須等待傳輸?shù)疆惖卣军c(diǎn)之后,才通報(bào)上層IO成功消息。異步復(fù)制,就是上層IO,主站點(diǎn)寫入成功,即向上層通報(bào)成功,然后后臺(tái)將數(shù)據(jù)通過(guò)網(wǎng)絡(luò)傳輸?shù)疆惖?。前者能保證兩地?cái)?shù)據(jù)的一致性,但是對(duì)上層響應(yīng)較慢。而后者不能實(shí)時(shí)保證兩地?cái)?shù)據(jù)的一致性,但是對(duì)上層響應(yīng)很快。
所有基于塊的備份措施,一般都是在底層設(shè)備上進(jìn)行,而不耗費(fèi)主機(jī)資源。
盤陣廠家的中高端產(chǎn)品,都提供遠(yuǎn)程鏡像服務(wù),比如IBM的PPRC,EMC的SRDF,HDS的Truecopy等等。
照數(shù)據(jù)保護(hù)
遠(yuǎn)程鏡像,或者本地鏡像,確實(shí)是對(duì)生產(chǎn)卷數(shù)據(jù)的一種很好的保護(hù),一旦生產(chǎn)卷故障,可以立即切換到鏡像卷。但是這個(gè)鏡像卷,一定要保持一直在線狀態(tài),主卷有寫IO操作,那么鏡像卷也逃不掉。如果此時(shí)想某一時(shí)刻的整個(gè)系統(tǒng),進(jìn)行備份,在鏡像的環(huán)境中,就只能停止應(yīng)用,使應(yīng)用不再對(duì)卷產(chǎn)生IO操作,然后將鏡像關(guān)系分離,稱作拆分鏡像,拆分之后,可以恢復(fù)上層的IO。此時(shí)的鏡像卷,就是主機(jī)停止IO那一刻的數(shù)據(jù)完整鏡像,此時(shí)可以用備份軟件,將鏡像卷上的數(shù)據(jù),備份到其他介質(zhì)。拆分鏡像,是為了讓鏡像卷可以被備份軟件操作。拆分之后,主卷所做的所有寫IO,會(huì)以bitmap的方式記錄下來(lái)(bitmap的概念,請(qǐng)參考《存儲(chǔ)秘史》文件系統(tǒng)相關(guān)知識(shí)),待備份完成之后,可以將鏡像關(guān)系恢復(fù),此時(shí)主卷和鏡像卷上的數(shù)據(jù)是不一致的,需要重新做同步。
可以看到,以上的過(guò)程是十分復(fù)雜繁瑣的,而且需要占用一塊和主卷相同容量大小的卷。關(guān)鍵是需要停掉主機(jī)IO,這對(duì)應(yīng)用會(huì)產(chǎn)生影響。為了解決這個(gè)難題,一種解決方案出現(xiàn)了,這就是快照技術(shù)??煺盏幕舅枷胧?,抓取某一時(shí)間點(diǎn),磁盤的所有數(shù)據(jù),就像急凍一樣,但是還不能真正凍住,主機(jī)的IO需要正常執(zhí)行。這怎么可能呢?快照就將其變成了可能??煺帐沁@樣實(shí)現(xiàn)的,即先在某一時(shí)間點(diǎn),對(duì)于這個(gè)時(shí)間點(diǎn)之后的所有上層的寫IO,先將這個(gè)IO對(duì)應(yīng)的塊上的數(shù)據(jù)復(fù)制到一個(gè)新的卷中存放,并做好原卷中的這個(gè)塊和新卷中塊的對(duì)應(yīng)關(guān)系記錄,然后才進(jìn)行上層IO的寫入。這樣,這一時(shí)間點(diǎn)上磁盤的數(shù)據(jù),便被保存下來(lái),就像做了急凍一樣。這種方法也叫做copy on write,也就是在發(fā)生IO寫之前,先將待更新塊中原來(lái)的數(shù)據(jù)復(fù)制出來(lái)保存,然后再做新數(shù)據(jù)的寫入,即寫時(shí)復(fù)制。還有一種實(shí)現(xiàn)塊快照的方法,叫做write redirect,當(dāng)寫IO到來(lái)的時(shí)候,將這個(gè)IO重定向到一個(gè)新的卷,而不是寫原來(lái)的卷,并做好新卷上的塊和原來(lái)卷所應(yīng)該被寫入塊的映射記錄。這樣也同樣保存下了這個(gè)時(shí)刻原來(lái)卷上的所有數(shù)據(jù),同時(shí)不影響后續(xù)讀寫IO操作,因?yàn)楸3至藟K映射關(guān)系。
在“照”下了這一時(shí)刻卷上的數(shù)據(jù)之后,為了保險(xiǎn)起見(jiàn),最好對(duì)那個(gè)時(shí)刻的數(shù)據(jù)做一個(gè)備份,也就是將這些數(shù)據(jù)在復(fù)制到另外的磁盤或者磁帶中。但是也可以不復(fù)制,而那時(shí)的數(shù)據(jù)依然會(huì)存在,直到手動(dòng)刪除這個(gè)快照。如果不對(duì)快照做備份,那么一旦此時(shí)卷數(shù)據(jù)失敗,快照的數(shù)據(jù)也不復(fù)存在。
不管是copy on write還是write redirect,只要上層有寫IO,這個(gè)IO塊就要占用新卷上的一個(gè)塊(因?yàn)橐A粼瓑K的內(nèi)容,不能被覆蓋),如果上層將原卷上的所有數(shù)據(jù)塊都寫更新了,那么新卷的容量就需要和原卷的數(shù)據(jù)量同樣大,甚至還大(預(yù)防新增數(shù)據(jù)寫入),才可以。但是通常應(yīng)用不會(huì)寫覆蓋面百分之百,做快照的時(shí)候,新卷的容量一般設(shè)置成原卷容量的30%就可以。
實(shí)際中一般都是用copy on write的方式做快照,因?yàn)閣rite redirect方式,每次寫IO都需要查一遍快映射表,速度慢,耗費(fèi)資源大。
值得說(shuō)明的是,快照所凍結(jié)下來(lái)的卷數(shù)據(jù),無(wú)異于一次意外掉電之后卷上的數(shù)據(jù)。為什么這么說(shuō)呢?我們可以比較一下,意外斷電同樣是保持了斷電那個(gè)時(shí)間點(diǎn)上的卷數(shù)據(jù)狀態(tài)。我們知道,不管是上層應(yīng)用,還是文件系統(tǒng),都有自己的緩存,文件系統(tǒng)緩存的是文件系統(tǒng)元數(shù)據(jù)。并不是每次數(shù)據(jù)的交互,都保存在磁盤上,它們可以暫時(shí)保存在內(nèi)存中,然后每隔一段時(shí)間(linux系統(tǒng)通常為30秒),批量flush到磁盤上。當(dāng)然編程的時(shí)候也可以將每次對(duì)內(nèi)存的寫,都flush到磁盤,但是這樣做效率和速度打了折扣。而且當(dāng)flush到磁盤的時(shí)候,并不是只做一次IO,如果數(shù)據(jù)量大,會(huì)對(duì)磁盤做多次IO,如果快照生成的時(shí)間恰恰在這連續(xù)的IO之間生成,那么此時(shí)卷上的數(shù)據(jù),實(shí)際上是有可能不一致的。磁盤IO是原子操作(atomic operation),而上層的一次事物操作,可以對(duì)應(yīng)底層的多次原子操作,這其中的一次原子操作,沒(méi)有業(yè)務(wù)意義,只有上層的一次完整的事物操作,才有意義。所以如果恰好在一個(gè)事物操作對(duì)應(yīng)的多個(gè)原子操作的中間,生成快照,那么此時(shí)的快照數(shù)據(jù),就是不完整的,不一致的。文件系統(tǒng)的機(jī)制是這樣的,它總是先寫入文件的實(shí)體數(shù)據(jù)到磁盤,而文件的元數(shù)據(jù),暫不寫到磁盤,而是先寫入緩存中。這種機(jī)制是有他的考慮的,我們想一攏?如果FS先把元數(shù)據(jù)寫入磁盤,而在準(zhǔn)備寫入文件實(shí)體數(shù)據(jù)的時(shí)候,突然斷電了,那么此時(shí)磁盤上的數(shù)據(jù)是這么一個(gè)狀態(tài):FS元數(shù)據(jù)中有這個(gè)文件的信息,但是實(shí)體數(shù)據(jù)并沒(méi)有被寫入對(duì)應(yīng)的扇區(qū),那么這些對(duì)應(yīng)的扇區(qū)上原來(lái)的數(shù)據(jù),便會(huì)被認(rèn)為就是這個(gè)文件的數(shù)據(jù),這顯然后果不堪設(shè)想。所以FS一定是先寫入文件實(shí)體數(shù)據(jù),完成之后再批量將元數(shù)據(jù)從緩存中flush到磁盤,如果在實(shí)體數(shù)據(jù)寫入磁盤,而元數(shù)據(jù)還沒(méi)有寫入磁盤之前,斷電,那么雖然此時(shí)文件實(shí)體數(shù)據(jù)在磁盤上,但是元數(shù)據(jù)沒(méi)有在磁盤上,也就是說(shuō)雖然有你這個(gè)人存在,但是你沒(méi)有身份證,那么你就不能公開(kāi)的進(jìn)行社會(huì)活動(dòng),因?yàn)槟悴皇沁@個(gè)國(guó)家的公民。雖然文件系統(tǒng)這么做,會(huì)丟失數(shù)據(jù),但是總比向應(yīng)用提交錯(cuò)誤的數(shù)據(jù)強(qiáng)!大家可以做一個(gè)實(shí)驗(yàn),就拿Windows來(lái)說(shuō),你創(chuàng)建一個(gè)文件,創(chuàng)建好之后,立即斷電,重啟之后,會(huì)發(fā)現(xiàn)剛才創(chuàng)建的文件沒(méi)了,或者你復(fù)制一個(gè)小文件,完成后立即斷電,重啟之后也會(huì)發(fā)現(xiàn),復(fù)制的文件不見(jiàn)了,為什么?明明創(chuàng)建好的,文件也復(fù)制好的,為什么斷電重啟就沒(méi)了呢?原因很簡(jiǎn)單,因?yàn)槟銛嚯姷臅r(shí)候,F(xiàn)S還沒(méi)有把元數(shù)據(jù)flush到磁盤上,你就給斷電了,此時(shí)文件實(shí)體數(shù)據(jù)雖然還在,但是元數(shù)據(jù)中沒(méi)有,那么當(dāng)然看不到它了。
總之,快照極有可能生成一份存在不一致的卷數(shù)據(jù)。這也沒(méi)有辦法,如果用這份數(shù)據(jù)做恢復(fù),那么就必須承擔(dān)數(shù)據(jù)不一致的風(fēng)險(xiǎn)。最保險(xiǎn)的備份,就是將主機(jī)停機(jī),此時(shí)存儲(chǔ)上的數(shù)據(jù),一定是一致的。但是誰(shuí)能忍受停機(jī)所帶來(lái)的損失?所以只能在停機(jī)和一致性之間找一個(gè)平衡點(diǎn)。而快照是最方便的。
有些快照解決方案,會(huì)在主機(jī)上安裝一個(gè)代理軟件,當(dāng)執(zhí)行快照之前,代理會(huì)通知應(yīng)用或者文件系統(tǒng)將緩存中的數(shù)據(jù)全部flush到磁盤,然后立即生成快照,這樣,一致性就得到了保護(hù)。不過(guò)相應(yīng)的也耗費(fèi)了一定的主機(jī)資源和網(wǎng)絡(luò)資源。
Continuos Data Protect(CDP,連續(xù)數(shù)據(jù)保護(hù))
SNIA對(duì)于CDP給出了如下的定義:持續(xù)數(shù)據(jù)保護(hù)(CDP)是這樣一種在不影響主要數(shù)據(jù)運(yùn)行的前提下,可以實(shí)現(xiàn)持續(xù)捕捉或跟蹤目標(biāo)數(shù)據(jù)所發(fā)生的任何改變,并且能夠恢復(fù)到此前任意時(shí)間點(diǎn)的方法。CDP系統(tǒng)能夠提供塊級(jí)、文件級(jí)和應(yīng)用級(jí)的備份。
有一類所謂Near CDP產(chǎn)品,這類產(chǎn)品,一般都是生成高頻率的快照而已,比如一小時(shí)幾十次,上百次等等。用這種方法來(lái)保證數(shù)據(jù)恢復(fù)的粒度足夠細(xì)。
快照,每做一次快照,只能保存那個(gè)時(shí)間點(diǎn)卷上的數(shù)據(jù)狀態(tài),快照之后的卷數(shù)據(jù)不會(huì)被保存下來(lái)。CDP是這樣一種機(jī)制,即它可以保護(hù)從某時(shí)刻開(kāi)始,卷或者文件在任意此后的時(shí)刻的數(shù)據(jù)狀態(tài),也就是數(shù)據(jù)的每次改變,都會(huì)被記錄下來(lái),無(wú)一遺漏。這個(gè)機(jī)制乍一看非常神奇,其實(shí)它的底層只不過(guò)是比快照多了一些考慮而已,下面我們就來(lái)分析它的實(shí)現(xiàn)原理。
文件級(jí)的CDP
顧名思義,文件級(jí)CDP,就是通過(guò)調(diào)用文件系統(tǒng)的相關(guān)函數(shù),監(jiān)視文件系統(tǒng)動(dòng)作,文件的每一次變化,都會(huì)被記錄下來(lái)。這個(gè)功能是分析應(yīng)用對(duì)文件系統(tǒng)的IO數(shù)據(jù)流,然后計(jì)算出文件變化的部分,將其保存在CDP倉(cāng)庫(kù)設(shè)備(存放CDP數(shù)據(jù)的介質(zhì))中。每次對(duì)文件的改變,都會(huì)被記錄下來(lái)??梢詫?duì)一個(gè)文件,或者一個(gè)目錄,甚至一個(gè)卷來(lái)監(jiān)控。文件級(jí)的CDP方案,一般需要在生產(chǎn)主機(jī)上安裝代理,用來(lái)監(jiān)控文件系統(tǒng)IO,并將變化的數(shù)據(jù)信息傳送到CDP倉(cāng)庫(kù)介質(zhì)中。文件級(jí)的CDP,能夠保證數(shù)據(jù)的一致性。因?yàn)樗亲饔糜谖募到y(tǒng)層次,捕獲的是完整事物。
塊級(jí)的CDP
塊級(jí)的CDP,就是捕獲底層卷的寫IO變化,并將每次變化的塊數(shù)據(jù)保存下來(lái)。我們?cè)谶@里不探討具體產(chǎn)品的架構(gòu),而只對(duì)其底層原理,作一個(gè)細(xì)致的描述。
CDP起源于linux下的CDP模塊。它持續(xù)地捕獲所有I/O請(qǐng)求,并且為在這些請(qǐng)求打上時(shí)間戳標(biāo)志。它將數(shù)據(jù)變化以及時(shí)間戳保存下來(lái),以便恢復(fù)到過(guò)去的任意時(shí)刻。
在linux的CDP實(shí)現(xiàn)中,包含下列三個(gè)設(shè)備:
主機(jī)磁盤設(shè)備(host disk)
CDP倉(cāng)庫(kù)設(shè)備(repository)
CDP元數(shù)據(jù)設(shè)備(metadata)
CDP代碼對(duì)機(jī)磁盤設(shè)備在任意時(shí)刻所作的寫操作都記錄下來(lái),實(shí)體數(shù)據(jù)順序?qū)懭隒DP倉(cāng)庫(kù)設(shè)備中,對(duì)于這些實(shí)體數(shù)據(jù)塊的描述信息,則被寫入到CDP元數(shù)據(jù)設(shè)備的對(duì)應(yīng)扇區(qū)。
元數(shù)據(jù)包含以下信息:
struct metadata {
int hrs, min, sec; 該數(shù)據(jù)塊被寫入主機(jī)磁盤設(shè)備的時(shí)間;
unsigned int bisize; 該數(shù)據(jù)塊的以字節(jié)為單位的長(zhǎng)度;
sector_t cdp_sector; CDP倉(cāng)庫(kù)設(shè)備中對(duì)應(yīng)數(shù)據(jù)塊的起始扇區(qū)編號(hào);
sector_t host_sector; 該數(shù)據(jù)塊在主機(jī)磁盤設(shè)備中的起始扇區(qū)編號(hào);
};
下圖反映了主機(jī)磁盤設(shè)備和CDP倉(cāng)庫(kù)設(shè)備之間的關(guān)系。CDP倉(cāng)庫(kù)設(shè)備中按時(shí)間順序保存了對(duì)主機(jī)磁盤設(shè)備的數(shù)據(jù)修改。A為主機(jī)磁盤設(shè)備上的一個(gè)扇區(qū),該扇區(qū)在9:00和9:05分別進(jìn)行了修改,它在CDP倉(cāng)庫(kù)設(shè)備中對(duì)應(yīng)的扇區(qū)分別為A1和A2。
下圖反映了CDP倉(cāng)庫(kù)設(shè)備和CDP元數(shù)據(jù)設(shè)備之間的關(guān)系,它們以寫入順序一一對(duì)應(yīng)。CDP倉(cāng)庫(kù)設(shè)備中的一個(gè)元數(shù)據(jù)對(duì)應(yīng)CDP元數(shù)據(jù)設(shè)備中一個(gè)I/O請(qǐng)求,實(shí)際上可能是多個(gè)扇區(qū)。具體扇區(qū)數(shù)由元數(shù)據(jù)中的bisize指定,而起始扇區(qū)位置由cdp_sector指定。
全局變量maddr保存了下一個(gè)I/O請(qǐng)求在CDP倉(cāng)庫(kù)設(shè)備上執(zhí)行的地址(起始扇區(qū)編號(hào))。maddr的初值被定義為宏START_METADATA(0)。
unsigned int maddr = START_METADATA;
當(dāng)一個(gè)寫請(qǐng)求到來(lái)時(shí),對(duì)應(yīng)數(shù)據(jù)被寫到CDP倉(cāng)庫(kù)設(shè)備中,這時(shí)所作的操作如下:
將寫入CDP倉(cāng)庫(kù)設(shè)備的數(shù)據(jù)塊起始扇區(qū)編號(hào)設(shè)置為maddr;
根據(jù)要寫入主機(jī)磁盤設(shè)備的數(shù)據(jù)塊的扇區(qū)數(shù)目增加maddr。
這時(shí),我們要將這里寫入的CDP倉(cāng)庫(kù)設(shè)備的數(shù)據(jù)塊編號(hào)記錄下來(lái)以便構(gòu)造對(duì)應(yīng)的元數(shù)據(jù)。
CDP元數(shù)據(jù)設(shè)備
全局變量taddr保存了下一個(gè)I/O請(qǐng)求對(duì)應(yīng)的元數(shù)據(jù)在CDP元數(shù)據(jù)設(shè)備中保存的地址(起始扇區(qū)編號(hào))。 taddr的初值被定義為宏START_METADATA(0)。
unsigned int taddr = START_METADATA;
當(dāng)一個(gè)寫請(qǐng)求到來(lái)時(shí),對(duì)應(yīng)的元數(shù)據(jù)被記錄在CDP元數(shù)據(jù)設(shè)備中。
為了簡(jiǎn)單起見(jiàn),在元數(shù)據(jù)設(shè)備上,一個(gè)扇區(qū)(512字節(jié))只保存一個(gè)元數(shù)據(jù)信息(只有32字節(jié)),這樣浪費(fèi)了大量的存儲(chǔ)空間,但對(duì)元數(shù)據(jù)設(shè)備的處理卻非常簡(jiǎn)單:
將寫入CDP元數(shù)據(jù)設(shè)備的元數(shù)據(jù)起始扇區(qū)編號(hào)設(shè)置為taddr,長(zhǎng)度為1個(gè)扇區(qū);
將taddr增1。
請(qǐng)求處理過(guò)程
請(qǐng)求處理過(guò)程是從make_request函數(shù)開(kāi)始的。考慮到讀請(qǐng)求的處理的相似性,甚至更為簡(jiǎn)單,我們這里只分析對(duì)寫請(qǐng)求的處理過(guò)程。我們首先獲得當(dāng)前的系統(tǒng)時(shí)間。之后,寫請(qǐng)求bio結(jié)構(gòu)(為說(shuō)明方便,我們記為B)被分為三個(gè)寫請(qǐng)求bio結(jié)構(gòu)(分別為B0、B1和B2)。這三個(gè)bio結(jié)構(gòu)的作用是:
B0:將數(shù)據(jù)塊寫到主機(jī)磁盤設(shè)備;
B1:將數(shù)據(jù)塊寫到CDP倉(cāng)庫(kù)設(shè)備;
B2:將元數(shù)據(jù)寫到CDP元數(shù)據(jù)設(shè)備。
同其它塊設(shè)備驅(qū)動(dòng)程序的實(shí)現(xiàn)一樣。我們從B克隆產(chǎn)生B0、B1和B2。然后重定向它們要處理的設(shè)備,即bi_bdev域。另外一個(gè)大的變動(dòng)是重新設(shè)置了bi_end_io域,用于在I/O請(qǐng)求完成之后進(jìn)行善后處理。
為了處理善后,還將B0、B1和B2的bi_private指向同一個(gè)cdp_bio1結(jié)構(gòu)。從這個(gè)結(jié)構(gòu),我們要能夠回到對(duì)B的處理。
struct cdp_bio {
struct bio *master_bio; 原來(lái)的bio,通過(guò)這個(gè)域我們可以從B0、B1、B2找到B
struct bio *bios[3]; 如果IO為WRITE,這個(gè)指針數(shù)組分別指向B0、B1、B2,為何需要這個(gè)域?
atomic_t remaining; 這里一個(gè)計(jì)數(shù)器,我們后面將解釋。
unsigned long state; 在I/O完成方法中使用
};
善后工作的主要目的是:在B0、B1和B2都執(zhí)行完成后,回去執(zhí)行B,為此,我們需要一個(gè)“have we finished”計(jì)數(shù)器,這就是原子整型變量remaining。在構(gòu)造B0、B1、B2時(shí)分別遞增,同時(shí)在B0、B1和B2的I/O完成方法中遞減,最后根據(jù)該值是否遞減到0,來(lái)判斷B0、B1和B2是否都已經(jīng)執(zhí)行完畢。為了防止B0在構(gòu)造后,在B1和B2構(gòu)造之前就執(zhí)行到B0的I/O完成方法,從而使得remaining變成0,這種錯(cuò)誤情況。我們沒(méi)有將remaining的初值設(shè)置為0,而是設(shè)為1。并在B0、B1、B2都構(gòu)造完成執(zhí)行遞減一次。
B0、B1、B2都執(zhí)行完成之后,進(jìn)行如下的處理:
調(diào)用B的善后處理函數(shù);
釋放期間分配的數(shù)據(jù)結(jié)構(gòu);
向上層buffer cache返回成功/錯(cuò)誤碼。
另一個(gè)需要說(shuō)明的是對(duì)B2的構(gòu)造,這個(gè)bio結(jié)構(gòu)需要處理的是元數(shù)據(jù)。時(shí)間戳已經(jīng)在進(jìn)入make_request時(shí)獲得了保存,而對(duì)主機(jī)磁盤設(shè)備操作的起始扇區(qū)和長(zhǎng)度從B中可以獲得,對(duì)應(yīng)的CDP倉(cāng)庫(kù)和CDP元數(shù)據(jù)的起始地址分別保存在全局變量maddr和taddr中。
數(shù)據(jù)恢復(fù)過(guò)程
我們可以將數(shù)據(jù)恢復(fù)到以前的任意時(shí)刻。CDP實(shí)現(xiàn)代碼中提供了一個(gè)blk_ioctl函數(shù),用戶空間以GET_TIME為參數(shù)調(diào)用該函數(shù),將主機(jī)磁盤設(shè)備中的數(shù)據(jù)恢復(fù)到指定的時(shí)間點(diǎn)。恢復(fù)的過(guò)程分為兩步:
1. 順序讀取CDP元數(shù)據(jù)設(shè)備的所有扇區(qū),構(gòu)造一個(gè)從主機(jī)磁盤設(shè)備數(shù)據(jù)塊到CDP倉(cāng)庫(kù)設(shè)備的(在這個(gè)時(shí)間點(diǎn)之前)更新數(shù)據(jù)塊的映射。其結(jié)果保存在以mt_home為首的(映射表)鏈表中。
這里需要構(gòu)造taddr個(gè)對(duì)CDP元數(shù)據(jù)設(shè)備的讀請(qǐng)求,每個(gè)請(qǐng)求讀取一個(gè)扇區(qū)。在這些請(qǐng)求的I/O完成方法中,從讀到的數(shù)據(jù)中構(gòu)造元數(shù)據(jù),并遞減計(jì)數(shù)器count。
如果元數(shù)據(jù)中的時(shí)間戳早于或等于指定的恢復(fù)時(shí)間點(diǎn),則需要添加或修改mt_home鏈表的元數(shù)據(jù)結(jié)構(gòu)。需要說(shuō)明的是,這些項(xiàng)是以host_sector為關(guān)鍵字索引的,因此添加或修改取決于前面是否出現(xiàn)對(duì)同一個(gè)host_sector的修改。我們以順序方式讀取的過(guò)程中,可以保證host_sector(在指定的恢復(fù)時(shí)間點(diǎn)之前)的最新修改cdp_sector會(huì)出現(xiàn)在這個(gè)鏈表中。
由于計(jì)數(shù)器count為taddr,如果它遞減為0,說(shuō)明CDP元數(shù)據(jù)設(shè)備中的所有數(shù)據(jù)均已讀出并處理,這時(shí)我們可以繼續(xù)往后面執(zhí)行。
2. 從CDP倉(cāng)庫(kù)設(shè)備中讀取這些更新的數(shù)據(jù)塊,構(gòu)造以mt_bi_home為首的鏈表。
同上面的處理類似,我們需要為mt_home鏈表中的每一項(xiàng)構(gòu)造對(duì)CDP倉(cāng)庫(kù)設(shè)備的讀請(qǐng)求,每個(gè)請(qǐng)求在CDP倉(cāng)庫(kù)設(shè)備的起始編號(hào)取決于cdp_sector域,長(zhǎng)度則根據(jù)bisize而定。這個(gè)請(qǐng)求讀出的數(shù)據(jù)需要被寫入到主機(jī)磁盤設(shè)備中,為此我們?cè)谧x請(qǐng)求I/O完成函數(shù)中,構(gòu)造一個(gè)對(duì)應(yīng)的往主機(jī)磁盤設(shè)備的寫請(qǐng)求bio,該寫請(qǐng)求的起始編號(hào)取決于host_sector域,長(zhǎng)度根據(jù)bisize而定,而要寫入的數(shù)據(jù)是剛剛從CDP倉(cāng)庫(kù)設(shè)備中讀出的數(shù)據(jù)。另外,在讀請(qǐng)求I/O完成函數(shù)中,還要遞減一個(gè)計(jì)數(shù)器,當(dāng)該計(jì)數(shù)器遞減到0時(shí),說(shuō)明我們已經(jīng)全部處理了mt_home鏈表中的項(xiàng),這時(shí)得到一個(gè)以mr_bio_home為首,每項(xiàng)中都指向一個(gè)bio結(jié)構(gòu)的鏈表。
struct list_head mt_home; //BIO更新鏈表
struct most_recent_blocks { //BIO更新表項(xiàng)
struct bio *mrbio;
struct list_head list;
};
3. 將mt_bi_home鏈表的數(shù)據(jù)塊都恢復(fù)到主機(jī)磁盤設(shè)備中。
這個(gè)操作相對(duì)比較簡(jiǎn)單,我們只需要在主機(jī)磁盤設(shè)備上執(zhí)行mt_bi_home鏈表的每一個(gè)bio請(qǐng)求項(xiàng)即可。當(dāng)然,我們要在這些請(qǐng)求項(xiàng)的I/O完成方法中做善后處理,即如果所有請(qǐng)求項(xiàng)都已經(jīng)執(zhí)行完畢,則釋放mt_home鏈表和mt_bi_home鏈表。