1. Hadoop 1.x 版本 fsimage和edits合併實現原理 node
在NameNode運行期間,HDFS的全部更新操做都是直接寫到edits中,長此以往edits文件將會變得很大;雖然這對NameNode運行時候是沒有什麼影響的,可是咱們知道當NameNode重啓的時候,NameNode先將fsimage裏面的全部內容映像到內存中,而後再一條一條地執行edits中的記錄,當edits文件很是大的時候,會致使NameNode啓動操做很是地慢,而在這段時間內HDFS系統處於安全模式,這顯然不是用戶要求的。能不能在NameNode運行的時候使得edits文件變小一些呢?實際上是能夠的,本文主要是針對Hadoop 1.x版本,說明其是怎麼將edits和fsimage文件合併的,Hadoop 2.x版本edits和fsimage文件合併是不一樣的。
用過Hadoop的用戶應該都知道在Hadoop裏面有個SecondaryNamenode進程,從名字看來你們很容易將它看成NameNode的熱備進程。其實真實的狀況不是這樣的。SecondaryNamenode是HDFS架構中的一個組成部分,它是用來保存namenode中對HDFS metadata的信息的備份,並減小namenode重啓的時間而設定的!通常都是將SecondaryNamenode單獨運行在一臺機器上,那麼SecondaryNamenode是如何namenode重啓的時間的呢?來看看SecondaryNamenode的工做狀況:
(1)、SecondaryNamenode會按期的和NameNode通訊,請求其中止使用edits文件,暫時將新的寫操做寫到一個新的文件edit.new上來,這個操做是瞬間完成,上層寫日誌的函數徹底感受不到差異;
(2)、SecondaryNamenode經過HTTP GET方式從NameNode上獲取到fsimage和edits文件,並下載到本地的相應目錄下;
(3)、SecondaryNamenode將下載下來的fsimage載入到內存,而後一條一條地執行edits文件中的各項更新操做,使得內存中的fsimage保存最新;這個過程就是edits和fsimage文件合併;
(4)、SecondaryNamenode執行完(3)操做以後,會經過post方式將新的fsimage文件發送到NameNode節點上
(5)、NameNode將從SecondaryNamenode接收到的新的fsimage替換舊的fsimage文件,同時將edit.new替換edits文件,經過這個過程edits就變小了!整個過程的執行能夠經過下面的圖說明:安全
在(1)步驟中,咱們談到SecondaryNamenode會按期的和NameNode通訊,這個是須要配置的,能夠經過core-site.xml進行配置,下面是默認的配置:架構
<property> <name>fs.checkpoint.period</name> <value>3600</value> <description>The number of seconds between two periodic checkpoints. </description> </property>
其實若是當fs.checkpoint.period配置的時間尚未到期,咱們也能夠經過判斷當前的edits大小來觸發一次合併的操做,能夠經過下面配置函數
<property> <name>fs.checkpoint.size</name> <value>67108864</value> <description>The size of the current edit log (in bytes) that triggers a periodic checkpoint even if the fs.checkpoint.period hasn't expired. </description> </property>
當edits文件大小超過以上配置,即便fs.checkpoint.period還沒到,也會進行一次合併。順便說說SecondaryNamenode下載下來的fsimage和edits暫時存放的路徑能夠經過下面的屬性進行配置:oop
<property> <name>fs.checkpoint.dir</name> <value>${hadoop.tmp.dir}/dfs/namesecondary</value> <description>Determines where on the local filesystem the DFS secondary name node should store the temporary images to merge. Ifthisis a comma-delimited list of directories then the image is replicated in all of the directories for redundancy. </description> </property> <property> <name>fs.checkpoint.edits.dir</name> <value>${fs.checkpoint.dir}</value> <description>Determines where on the local filesystem the DFS secondary name node should store the temporary edits to merge. Ifthisis a comma-delimited list of directoires then teh edits is replicated in all of the directoires for redundancy. Default value is same as fs.checkpoint.dir </description> </property>
從上面的描述咱們能夠看出,SecondaryNamenode根本就不是Namenode的一個熱備,其只是將fsimage和edits合併。其擁有的fsimage不是最新的,由於在他從NameNode下載fsimage和edits文件時候,新的更新操做已經寫到edit.new文件中去了。而這些更新在SecondaryNamenode是沒有同步到的!固然,若是NameNode中的fsimage真的出問題了,仍是能夠用SecondaryNamenode中的fsimage替換一下NameNode上的fsimage,雖然已經不是最新的fsimage,可是咱們能夠將損失減少到最少!post
2. 2.X 版本中fsimage和edits合併實現原理 this
咱們知道,在Hadoop 2.x中解決了NameNode的單點故障問題;同時SecondaryName已經不用了,而以前的Hadoop 1.x中是經過SecondaryName來合併fsimage和edits以此來減少edits文件的大小,從而減小NameNode重啓的時間。而在Hadoop 2.x中已經不用SecondaryName,那它是怎麼來實現fsimage和edits合併的呢?首先咱們得知道,在Hadoop 2.x中提供了HA機制(解決NameNode單點故障),能夠經過配置奇數個JournalNode來實現HA,如何配置今天就不談了!HA機制經過在同一個集羣中運行兩個NN(active NN & standby NN)來解決NameNode的單點故障,在任什麼時候間,只有一臺機器處於Active狀態;另外一臺機器是處於Standby狀態。Active NN負責集羣中全部客戶端的操做;而Standby NN主要用於備用,它主要維持足夠的狀態,若是必要,能夠提供快速的故障恢復。
爲了讓Standby NN的狀態和Active NN保持同步,即元數據保持一致,它們都將會和JournalNodes守護進程通訊。當Active NN執行任何有關命名空間的修改,它須要持久化到一半以上的JournalNodes上(經過edits log持久化存儲),而Standby NN負責觀察edits log的變化,它可以讀取從JNs中讀取edits信息,並更新其內部的命名空間。一旦Active NN出現故障,Standby NN將會保證從JNs中讀出了所有的Edits,而後切換成Active狀態。Standby NN讀取所有的edits可確保發生故障轉移以前,是和Active NN擁有徹底同步的命名空間狀態
那麼這種機制是如何實現fsimage和edits的合併?在standby NameNode節點上會一直運行一個叫作CheckpointerThread的線程,這個線程調用StandbyCheckpointer類的doWork()函數,而doWork函數會每隔Math.min(checkpointCheckPeriod, checkpointPeriod)秒來坐一次合併操做,相關代碼以下:線程
try{ Thread.sleep(1000* checkpointConf.getCheckPeriod()); }catch(InterruptedException ie) { } publiclonggetCheckPeriod() { returnMath.min(checkpointCheckPeriod, checkpointPeriod); } checkpointCheckPeriod = conf.getLong( DFS_NAMENODE_CHECKPOINT_CHECK_PERIOD_KEY, DFS_NAMENODE_CHECKPOINT_CHECK_PERIOD_DEFAULT); checkpointPeriod = conf.getLong(DFS_NAMENODE_CHECKPOINT_PERIOD_KEY, DFS_NAMENODE_CHECKPOINT_PERIOD_DEFAULT); try{ Thread.sleep(1000* checkpointConf.getCheckPeriod()); }catch(InterruptedException ie) { } publiclonggetCheckPeriod() { returnMath.min(checkpointCheckPeriod, checkpointPeriod); } checkpointCheckPeriod = conf.getLong( DFS_NAMENODE_CHECKPOINT_CHECK_PERIOD_KEY, DFS_NAMENODE_CHECKPOINT_CHECK_PERIOD_DEFAULT); checkpointPeriod = conf.getLong(DFS_NAMENODE_CHECKPOINT_PERIOD_KEY, DFS_NAMENODE_CHECKPOINT_PERIOD_DEFAULT);
上面的checkpointCheckPeriod和checkpointPeriod變量是經過獲取hdfs-site.xml如下兩個屬性的值獲得:日誌
<property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> <description>The number of seconds between two periodic checkpoints. </description> </property> <property> <name>dfs.namenode.checkpoint.check.period</name> <value>60</value> <description>The SecondaryNameNode and CheckpointNode will poll the NameNode every'dfs.namenode.checkpoint.check.period'seconds to query the number of uncheckpointed transactions. </description> </property>
當達到下面兩個條件的狀況下,將會執行一次checkpoint:code
booleanneedCheckpoint = false; if(uncheckpointed >= checkpointConf.getTxnCount()) { LOG.info("Triggering checkpoint because there have been " + uncheckpointed + " txns since the last checkpoint, which " + "exceeds the configured threshold " + checkpointConf.getTxnCount()); needCheckpoint = true; }elseif(secsSinceLast >= checkpointConf.getPeriod()) { LOG.info("Triggering checkpoint because it has been " + secsSinceLast + " seconds since the last checkpoint, which " + "exceeds the configured interval " + checkpointConf.getPeriod()); needCheckpoint = true; }
當上述needCheckpoint被設置成true的時候,StandbyCheckpointer類的doWork()函數將會調用doCheckpoint()函數正式處理checkpoint。當fsimage和edits的合併完成以後,它將會把合併後的fsimage上傳到Active NameNode節點上,Active NameNode節點下載完合併後的fsimage,再將舊的fsimage刪掉(Active NameNode上的)同時清除舊的edits文件。步驟能夠歸類以下:
(1)、配置好HA後,客戶端全部的更新操做將會寫到JournalNodes節點的共享目錄中,能夠經過下面配置
<property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://XXXX/mycluster</value> </property> <property> <name>dfs.journalnode.edits.dir</name> <value>/export1/hadoop2x/dfs/journal</value> </property>
(2)、Active Namenode和Standby NameNode從JournalNodes的edits共享目錄中同步edits到本身edits目錄中; (3)、Standby NameNode中的StandbyCheckpointer類會按期的檢查合併的條件是否成立,若是成立會合並fsimage和edits文件; (4)、Standby NameNode中的StandbyCheckpointer類合併完以後,將合併以後的fsimage上傳到Active NameNode相應目錄中; (5)、Active NameNode接到最新的fsimage文件以後,將舊的fsimage和edits文件清理掉; (6)、經過上面的幾步,fsimage和edits文件就完成了合併,因爲HA機制,會使得Standby NameNode和Active NameNode都擁有最新的fsimage和edits文件(以前Hadoop 1.x的SecondaryNameNode中的fsimage和edits不是最新的)