Hadoop基礎面試精選

Hadoop基礎面試精選

1、Hadoop1.x和Hadoop2.x的區別:
    a、1.x:Common(輔助工具)、HDFS(數據存儲)、MapReduce(計算+資源調度)
    b、2.x:Common(輔助工具)、HDFS(數據存儲)、MapReduce(計算)、Yarn(資源調度)
    答:在hadoop1.x時代中,hadoop中的mapreduce同時處理業務邏輯運算和資源調度,耦合性較大,
        在hadoop2.x時代中,增加了yarn。分擔了1.x版本的資源調度的工作,mapreduce只負責計算,性能也有所提升。

2、NameNode(NN):存儲文件的元數據,如文件名,文件目錄結構,文件屬性(生成文件時間、副本數、文件權限),以及每個文件的塊列表和塊所在的DataNode等。
   DataNode(DN):在本地文件系統存儲文件塊數據,以及塊數據的校驗和。
   Secondary NameNode(2NN):用來監控HDFS狀態的輔助後臺程序,每隔一段時間獲取HDFS元數據的快照。
                              並非NameNode的熱備。當NameNode掛掉的時候,它並不能馬上替換NameNode並提供服務,
                              輔助NameNode,分擔其工作量,比如定期合併Fsimage和Edits,並推送給NameNode。
                              在緊急情況下,可輔助恢復NameNode。
   Yarn(資源調度):包括 RM(resourceManager所有機器的資源的分配和調度)、NM(NodeManager 管理某個服務器的資源)、AM(applicationMaster負責數據的切分,爲應用程序申請資源並分配給內部
                     的任務,任務的監控和容錯)、Container(是yarn的資源抽象,封裝了某個節點上的多維度資源,如內存、cpu、磁盤、網絡等)
  
3、MapReduce:map階段並行處理數據
              reduce階段對map結果進行彙總
              
4、HDFS的優缺點:
    優點:a、高容錯性
            1)數據自動保存多個副本。通過增加副本的形式,提高容錯性
            2)某一個副本丟失以後,它可以自動恢復
        b、適合處理大數據
            1)數據規模:能夠處理數據規模達到GB、TB,甚至PB級別的數據
            2)文件規模:能夠處理百萬規模以上的文件數量,數量相當之大
        c、可構建在廉價機器上、通過多副本機制,提高可靠性。
    缺點:a、不適合低延時數據訪問,比如毫秒級的存儲數據,是做不到的
          b、無法高校的對大量小文件進行存儲
            1)存儲大量小文件的話,它會佔用NameNode大量的內存來存儲文件目錄和塊信息,是不可取的,因爲NameNode的內存總是有限的。
            2)小文件存儲的尋址時間會超過讀取時間(小文件量大,導致遍歷的時間就長),違反了HDFS的設計目標。
          c、不支持併發寫入,文件隨機修改。
            1)一個文件只能有一個寫,不允許多個線程同時寫;
            2)只支持數據append(追加),不支持文件的隨機修改。
    

    
5、尋址時間:HDFS中找到目標文件塊(block)所需要的時間。
原理:
    文件塊越大,尋址時間越短,但磁盤傳輸時間越長;
    文件塊越小,尋址時間越長,但磁盤傳輸時間越短。
一、爲什麼HDFS中塊(block)不能設置太大,也不能設置太小?
    1. 如果塊設置過大,
        一方面,從磁盤傳輸數據的時間會明顯大於尋址時間,導致程序在處理這塊數據時,變得非常慢;
        另一方面,mapreduce中的map任務通常一次只處理一個塊中的數據,如果塊過大運行速度也會很慢。
    2. 如果塊設置過小,
        一方面存放大量小文件會佔用NameNode中大量內存來存儲元數據,而NameNode的內存是有限的,不可取;
       另一方面文件塊過小,尋址時間增大,導致程序一直在找block的開始位置。
       因而,塊適當設置大一些,減少尋址時間,那麼傳輸一個由多個塊組成的文件的時間主要取決於磁盤的傳輸速率。
二、 HDFS中塊(block)的大小爲什麼設置爲128M?
    1. HDFS中平均尋址時間大概爲10ms;
    2. 經過前人的大量測試發現,尋址時間爲傳輸時間的1%時,爲最佳狀態;
        所以最佳傳輸時間爲10ms/0.01=1000ms=1s
    3. 目前磁盤的傳輸速率普遍爲100MB/s;
        計算出最佳block大小:100MB/s x 1s = 100MB
        所以我們設定block大小爲128MB。
    ps:實際在工業生產中,磁盤傳輸速率爲200MB/s時,一般設定block大小爲256MB
        磁盤傳輸速率爲400MB/s時,一般設定block大小爲512MB
    
6、HDFS namenode容錯機制
    1 遠程備份組成元數據持久狀態的文件
        將持久狀態寫入本地磁盤的同時,寫入一個遠程的網絡文件系統NFS(網絡文件系統Network File System,NFS),操作是實時且原子性的
        搭建DFS共享網絡文件系統,即使A服務器磁盤壞了,也不影響B服務器提供服務。
    2 運行secondary namenode(輔助namenode)
        輔助namenode主要是合併edits和fsimage,並保存合併後的fsimage
        namenode出現故障時,啓用輔助namenode,因爲輔助namenode上的fsimage未包含最近的edits文件,所以一般是將遠程NFS上的元數據信息拷貝到輔助namenode上作爲主namenode運行
    一,NameNode 
    HDFS集羣有兩類節點以管理者和工作者的工作模式運行,namenode就是其中的管理者。它管理着文件系統的命名空間,維護着文件系統樹及整棵樹的所有文件和目錄。這些信息以兩個文件的形式保存於內存或者磁盤,這兩個文件是:命名空間鏡像文件fsimage和編輯日誌文件edit logs ,同時namenode也記錄着每個文件中各個塊所在的數據節點信息。

    namenode對元數據的操作過程 
     
    圖中有兩個文件: 
    (1)fsimage:文件系統映射文件,也是元數據的鏡像文件(磁盤中),存儲某段時間namenode內存元數據信息。 
    (2)edits log:操作日誌文件。 
    這種工作方式的特點: 
    (1)namenode始終在內存中存儲元數據(metedata),使得“讀操作”更加快、 
    (2)有“寫請求”時,向edits文件寫入日誌,成功返回後才修改內存,並向客戶端返回。 
    (3)fsimage文件爲metedata的鏡像,不會隨時同步,與edits合併生成新的fsimage。

    從以上特點可以知道,edits文件會在集羣運行的過程中不斷增多,佔用更多的存儲空間,雖然有合併,但是隻有在namenode重啓時纔會進行。並且在實際工作環境很少重啓namenode, 
    這就帶來了一下問題: 
    (1)edits文件不斷增大,如何存儲和管理? 
    (2)因爲需要合併大量的edits文件生成fsimage,導致namenode重啓時間過長。 
    (3)一旦namenode宕機,用於恢復的fsiamge數據很舊,會造成大量數據的丟失。

    二,Secondary NameNode 
    上述問題的解決方案就是運行輔助namenode–Secondary NameNode,爲主namenode內存中的文件系統元數據創建檢查點,Secondary NameNode所做的不過是在文件系統中設置一個檢查點來幫助NameNode更好的工作。它不是要取代掉NameNode也不是NameNode的備份, 
    SecondaryNameNode有兩個作用,一是鏡像備份,二是日誌與鏡像的定期合併。兩個過程同時進行,稱爲checkpoint(檢查點)。 
    鏡像備份的作用:備份fsimage(fsimage是元數據發送檢查點時寫入文件); 
    日誌與鏡像的定期合併的作用:將Namenode中edits日誌和fsimage合併,防止如果Namenode節點故障,namenode下次啓動的時候,會把fsimage加載到內存中,應用edits log,edits log往往很大,導致操作往往很耗時。(這也是namenode容錯的一套機制)

    Secondary NameNode創建檢查點過程 

    Secondarynamenode工作過程 
    (1)SecondaryNameNode通知NameNode準備提交edits文件,此時主節點將新的寫操作數據記錄到一個新的文件edits.new中。 
    (2)SecondaryNameNode通過HTTP GET方式獲取NameNode的fsimage與edits文件(在SecondaryNameNode的current同級目錄下可見到 temp.check-point或者previous-checkpoint目錄,這些目錄中存儲着從namenode拷貝來的鏡像文件)。 
    (3)SecondaryNameNode開始合併獲取的上述兩個文件,產生一個新的fsimage文件fsimage.ckpt。 
    (4)SecondaryNameNode用HTTP POST方式發送fsimage.ckpt至NameNode。 
    (5)NameNode將fsimage.ckpt與edits.new文件分別重命名爲fsimage與edits,然後更新fstime,整個checkpoint過程到此結束。 
    SecondaryNameNode備份由三個參數控制fs.checkpoint.period控制週期(以秒爲單位,默認3600秒),fs.checkpoint.size控制日誌文件超過多少大小時合併(以字節爲單位,默認64M), dfs.http.address表示http地址,這個參數在SecondaryNameNode爲單獨節點時需要設置。
    從工作過程可以看出,SecondaryNameNode的重要作用是定期通過編輯日誌文件合併命名空間鏡像,以防止編輯日誌文件過大。SecondaryNameNode一般要在另一臺機器上運行,因爲它需要佔用大量的CPU時間與namenode相同容量的內存纔可以進行合併操作。它會保存合併後的命名空間鏡像的副本,並在namenode發生故障時啓用。
    
SecondaryNameNode的namesecondary/current目錄和主namenode的current目錄的佈局相同。
    好處:在主namenode發生故障時(假設沒有及時備份數據),可以從SecondaryNameNode恢復數據。
    2.故障恢復方法
        方法一:將SecondaryNameNode中數據拷貝到namenode存儲數據的目錄;
        方法二:使用-importCheckpoint選項啓動namenode守護進程,從而將SecondaryNameNode用作新的主namenode。

    如果手動的話,在生產上採用安全模式(safe mode) hdfs dfsadmin 命令去開啓安全模式


計算切片問題
    129M的文件分成2塊存儲(在集羣中的HDFS)
    本地模式中默認的blocksize:32M,集羣模式是128M。
    while (((double) bytesRemaining)/splitSize > 1.1) {}
    默認的切片splitSize是128M。129/128 小於1.1,則就切成一片(一個mapTask任務線程)
    141M/128M 剛好大於 1.1 那麼就分爲兩片,兩個mapTask任務數去執行

YARN中一些術語:
    兩個獨立的守護進程:RM和AM
        resource manager ,RM:負責管理整個集羣上所有應用程序計算資源的分配。
        application master ,AM:每一個應用程序的AM負責相應的d調度和協調,監視整個任務的生命週期,RM和AM協商集羣的計算資源。
    容器,containers:每個容器都有一個特定的內存上限,在這些容器上運行特定應用程序的進程,每個任務對應一個Containers,且只能在該container中運行。
                      container是由集羣ji節點上運行的節點管理器監視,以確保應用程序使用的資源不會超過分配給它的資源。
    節點管理器,node manager:管理每個節點上的資源和任務,主要有兩個作用:
                               定期向RM彙報該節點的資源使用情況和各個container的運行狀態;
                               接收並處理AM的任務啓動、停止等請求
        

YARN工作流程機制:
    (0)Mr程序提交到客戶端所在的節點
    (1)yarnrunner向Resourcemanager申請一個application。
    (2)rm將該應用程序的資源路徑返回給yarnrunner
    (3)該程序將運行所需資源提交到HDFS上
    (4)程序資源提交完畢後,申請運行mrAppMaster
    (5)RM將用戶的請求初始化成一個task
    (6)其中一個NodeManager領取到task任務。
    (7)該NodeManager創建容器Container,併產生MRAppmaster
    (8)Container從HDFS上拷貝資源到本地
    (9)MRAppmaster向RM 申請運行maptask容器
    (10)RM將運行maptask任務分配給另外兩個NodeManager,另兩個NodeManager分別領取任務並創建容器。
    (11)MR向兩個接收到任務的NodeManager發送程序啓動腳本,這兩個NodeManager分別啓動maptask,maptask對數據分區排序。
    (12)MRAppmaster向RM申請2個容器,運行reduce task。
    (13)reduce task向maptask獲取相應分區的數據。
    (14)程序運行完畢後,MR會向RM註銷自己。
    
    
map-reduce計算模型是Hadoop解決海量數據處理的戰略佈局,排序器/組合器/合併器是Hadoop解決計算節點性能的戰術實現
一、排序器(Sorter)
         對於Hadoop中排序器的設計,我不得不得先向Hadoop的設計大牛們深深的鞠上一躬,它牛B了,太精彩了。他們將排序問題抽象成了一個框架,或者說是一個排序模型:
        上面的排序模型將排序問題描述成這樣的一個過程:排序器不斷地對待排序的記錄集進行某兩條記錄的比較與交換。也就是說,任何一種排序算法只對帶排序的記錄集進行兩種基本操作:比較兩條記錄的大小、交換兩條記錄在帶排序記錄集中的位置,這就是Hadoop大牛們對排序問題的精簡定義,這樣的定義來源於他們對問題在最本質上的瞭解。我不得不說只有對問題有了最深入、最本質的瞭解之後才能設計出最抽象、最準確的解決方案,對已實現的解決方法的不斷重構只能治標不能治本。在Sorter中實現某種排序算法,在Sortable中實現某種可排序的數據集,這樣使得排序算法與待排序的數據集分開,排序算法永遠也不知道也不需要知道它正在對哪個數據類型的數據集進行排序。而Hadoop在其內部這是這樣設計的。
         Hadoop關於可排序的數據集定義了一個抽象接口IndexedSortable,也就是說任何能夠排序的數據集必須要實現兩個方法,一是能夠比較它的數據集中任意兩項的大小,二是能夠交換它的數據集中任意兩項的位置;排序算法的實現定義了一個抽象接口IndexedSorter,它定義了兩個方法,其中的一個方法還可以報告當前排序的完成進度。

二、組合器(Combiner)
         Hadoop在其內部利用組合器來局部合併具有相同key的key-value記錄,組合器的設計大致同排序器的設計一樣,也是將合併操作和待合併的數據分開,這個組合器框架設計如下:         Hadoop中的合併器一般合併的key-value數據來自與內存,然後把合併後的結果按照一定的組織格式寫入磁盤文件作爲中間數據,待最後彙總合併,我們把每一次合併後的這種中間結果看做一個段。在Hadoop中是這樣實現這個組合框架的: 
        Hadoop中的組合器的實現主要用來處理key-value類型的數據,它先把帶合併的所有的key-value結合按照key值來聚合,這樣就使得相同key值的key-value記錄被保存到同一個迭代器(Iterator)中,然後把一個個迭代器結構組合器來處理,最後每一迭代器的處理結果被交給了收集器(Collector)來保存。
三、合併器(Merger)

        這裏的合併器(Merger)不同於上面介紹的組合器(Combiner),它主要是正對上面組合器生成的最後結果進行合併,也就是合併所有的中間段,這個框架在Hadoop內部是這樣設計的:
     Hadoop中合併器(Merger)的設計類似於它的組合器(Combiner),唯一不同的就是這個聚合迭代器的來源略有不同,合併器中的每一個迭代器來自於所有的中間段中屬於相同類的key-value,所以對每一中間段,合併器都生成了一個對應的段讀取器來讀取段(SegmentReader)中的key-value值。主要看一下與段讀取器(SegmentReader)相關的實現類:

四、總結
       在本文,我係統的介紹了Hadoop對排序器/組合器/合併器的設計,Hadoop對它們的設計可以說是站在一個好高的層次,因此我們就可以把這些框架移植到其它引用場景下,甚至無需修改任何代碼。
       
       
MepReduce面試題:MapReduce中排序發生在哪幾個階段?這些排序是否可以避免?爲什麼?
      如果任務沒有設置reducer個數,爲0的話,則整個map過程中不會sort
 答:1.map最後階段進行partition分區,一般使用job.setPartitionerClass設置的類,如果沒有自定義Key的hashCode()方法進行分區。在map階段寫出到環形緩衝區,在環形緩衝區溢寫時會進行一次排序,        每個分區內部調用job.setSortComparatorClass設置的key的比較函數類進行排序,如果沒有則使用Key的實現的compareTo方法。

    2.在歸併每一個maptask的環形緩衝區的所有溢寫文件的時候也會再次進行排序
    3.當reduce接收到所有map傳輸過來的數據之後,對每一個分區的數據進行merge並排序,調用job.setSortComparatorClass設置的key比較函數類對所有數據對排序,如果沒有則使用Key的實現的compareTo方法。
    4.緊接着使用job.setGroupingComparatorClass設置的分組函數類,進行分組,同一個Key的value放在一個迭代器裏面。如果未指定GroupingComparatorClass則則使用Key的實現的compareTo方法來對其分組。

    Hadoop1.0中不可避免  hadoop2.0中可以關閉,將reducetask設置爲0

MapReduce中的數據流動
    最簡單的過程: map - reduce
    定製了partitioner以將map的結果送往指定reducer的過程: map - partition - reduce
    增加了在本地先進行一次reduce(優化)的過程: map - combine - partition - reduce
    map端執行自定義的mapper後---》執行sort(先按分區排序、如果在同一個區下,則按key排序,默認使用快排)---》執行combiner組合器----》
    將排序後的buffer生成一個或者多個文件(spill溢寫到臨時目錄)名爲spill0.out-----》將1個或多個溢spill寫文件合併meger生成file.out文件,
    reduce端---》將多個file.out合併成map_0.out.merged文件(排序後的)
    注:排序先是按照從大到小排序的,然後寫入的時候重新存入新的緩存數組中,不過是從小到大的順序重新存入,最後關閉的時候,寫入到磁盤產生spill0.out的有序文件。
    如果一個map任務,split切片數爲1,溢寫出兩個spill0.out和spill1.out已排好序的文件,在合併merger的時候,分別讀取出由配置的"io.file.buffer.size"的參數值
    4096個緩衝字節數
    
    如果超過0.8的閾值,則會通知spillThread線程溢出寫入到臨時文件中,如果不超過,,在最後的關閉output時候調用MapOutputBuffer的flush也會溢寫到文件
    
    
    JobSumitter-->LocalJobRunner.run()-->MapTaskRunnable.run()-->MapTask.run()-->MapTask.runNewMapper(),創建MapOutputBuffer採集器new NewOutputCollector()
    -->調用用戶寫的map方法,context.write()方法內部最終調用的是MapOutputBuffer.collect()方法,該方法去寫入並判斷是否超過默認的100M的閾值100*0.8=80M,如果超過
    80M,那麼就喚醒spillThread溢寫的線程去往磁盤就寫,當然了,在溢寫的之前先進行對溢寫的數據進行排序,這樣,每個溢寫文件都是有序的,這個spillThread線程是在new MapOutputBuffer()的構造方法裏去開啓的,wait()狀態,溢寫線程邊寫入磁盤,主線程
    也在繼續往緩存中寫入數據,緩存默認是100M,如果溢寫還沒完成,緩存已經都使用完畢,那麼主線程就等待溢寫線程完成後纔回去喚醒主線程繼續,當主線程都讀取完畢後再次
    調用MapOutputBuffer的flush()也就是最後的sortAndSpill()排序且溢寫到磁盤(如果reducer個數不止一個,在此會對元數據kvmeta數據進行分區操作),
    --->megerparts()方法進行spill文件的合併並且採用歸併算法對多個有序的spill文件進行整合成一個fill.out文件,如果有分區(reducer個數不爲1)則輸出的fill.out文件
    是分區後的整合的文件,默認採用hash取模分區,在fill.out的文件頭標記出分區標識,(分區有利於減少reduce的壓力,以及整合的spill文件也減輕壓力,還有map端
    的combiner合併器也是有助於減輕reduce的壓力)
    
比較器,對比器
    Map端:是如何開始調用的呢?在所有文件都spill溢寫出前開始調用sortAndSpill方法,調用sort去排序,則調用自己的對比器,對Key進行排序。
        注意:map端是對key排序
        1:xml配置屬性mapreduce.job.output.key.comparator.class 如果未配置走2.
        2:api形式:job.setSortComparatorClass(ComboKeyComparator.class);
        3:如果都沒有從map緩存獲取
            WritableComparator.get(getMapOutputKeyClass().asSubclass(WritableComparable.class), this);
            獲取設置的MapOutputKeyClass作爲key的對比器,形如IntWritable類,內部類繼承了WritableComparator
            如果緩存還沒有則創建父類WritableComparator對象作爲默認對比器
    Reduce端(分組對比器):是如何開始調用的呢?是在reduce的run方法開始遍歷context.nextKey()的時候調用分組對比器,將key同一組的分在一起,對自定義key才起作用。
        1:xml配置屬性mapreduce.job.output.group.comparator.class 如果未配置走2
        2:api形式:job.setGroupingComparatorClass(YearGroupComparator.class);
        3:在reduce的run方法開始獲取分組對比器RawComparator comparator = job.getOutputValueGroupingComparator();
            如果都沒有配置那麼就獲取Map端的對比器流程。
    
    combiner就是map端的reduce爲了減輕shuffle的網絡之間的傳輸,在map端預先將key作聚合,比如:
    hello 1 hello 1 hello 1 ....聚合爲 hello 3 直接key 和聚合後的數字3傳輸即可,極大的減少網絡負載。
    

排序:
    部分排序:
        reduce就是按照key進行排序。
    輔助排序 又稱 二次排序:
        GroupingComparator分組(輔助排序):對Reduce階段的數據根據某一個或幾個字段進行分組。
    
    全排序操作:
         1、定義一個reduce。缺點:會造成數據傾斜。
         2、自定義分區函數:自行根據總量來分析
                比如100個數,3個reduce,則分了3個分區,對所有的結果進行排序(輸出的三個文件合併起來是整個有序的)
                可以這樣,100/3=33, 0-33--》分區0,33-66--》分區1,66-100--》分區3,這樣每個分區都是有序的,整合起來就是有序的
         3、採用hadoop的採樣機制(TotalOrderPartitioner):原理就是對部分數據採用得出一個區間值,然後根據這個區間進行分區,和自定義分區一樣。
                    InputSampler採樣分爲三種:
                        切片採樣splitSampler:只採樣一個分片中的前n條記錄,由於由於並未從所有分片中廣泛採樣,該採樣器並不適合已經排序好的順序
                        隨機採樣randomSampler:
                        間隔採樣IntervalSampler:已一定的j間隔定期從分片中選擇鍵,對已經排序好的數據來說是一個很好的選擇。
          
    倒排序:
        kv對調
            
    二次排序  又稱 輔助排序:對value進行排序。key是一次排序
        Key是可以排序的。
        需要對value排序。
        1.自定義key
        2.自定義分區類,按照年份分區
        3.定義Key排序對比器(map端的排序)
        4.定義分組對比器(reduce端的)
        
map端join連接操作:
    小表+大表:在map端的mapper.setup()可以將小表的數據初始化到內存當中,在map端即可實現join連接輸出
reduce端的join連接操作:
    大表+大表:解決方式和二次排序類似

輸入格式有哪些:
    1、TextInputFormat  文本
    2、KeyValueTextInputFormat     k-v 對
    3、SequenceFileInputFormat    序列文件
    4、CombineTextInputFormat    合併文本輸入格式,合併多個小文件
    5、NLineInputFormat            換行輸入格式
    6、MutliInputFormat                            多輸入文件

解決數據傾斜skew:
    1、定義合成器Combiner類(map端的reduce)在map端 hash分區後,調用Combiner合成將同一key進行聚合累加成一個key 和一個總數,最後在shuffle到reduce端,減輕壓力。
    2、自定義分區函數,但是一次的job執行統計的話,數據會比較分散,不是一個完整的總數,如果需要統計總數,需要再次對part-r-0000~part-r-0100個文件繼續執行一次job。
        兩次job的執行
    
    網上收集:
        2.增加reduce的個數,這適用於第二種情況(唯一值比較多,這個字段的某些值有遠遠多於其他值的記錄數,但是它的佔比也小於百分之一或千分之一),我們知道,這種情況下,
          最容易造成的結果就是大量相同key被partition到一個分區,從而一個reduce執行了大量的工作,而如果我們增加了reduce的個數,這種情況相對來說會減輕很多,
          畢竟計算的節點多了,就算工作量還是不均勻的,那也要小很多。
        3.自定義分區,這需要用戶自己繼承partition類,指定分區策略,這種方式效果比較顯著。
        4.重新設計key,有一種方案是在map階段時給key加上一個隨機數,有了隨機數的key就不會被大量的分配到同一節點(小几率),待到reduce後再把隨機數去掉即可。
        5.使用combinner合併,combinner是在map階段,reduce之前的一箇中間階段,在這個階段可以選擇性的把大量的相同key數據先進行一個合併,可以看做是local  
           reduce,然後再交給reduce來處理,這樣做的好處很多,即減輕了map端向reduce端發送的數據量(減輕了網絡帶寬),也減輕了map端和reduce端中間
          的shuffle階段的數據拉取數量(本地化磁盤IO速率),推薦使用這種方法。
鏈式處理 chainMapper
    ChainMapper
-----------------
    ChainMapper.addMapper(conf, AMap.class, LongWritable.class, Text.class,Text.class, Text.class, true, mapAConf);
     可以設置多個mapper類,1個reduce 後面可以0個或者多個mapper,可以很明顯的降低IO,因爲都是在內存中執行,執行完就立即交給下一個mapper處理
     map+ / reduce map*

MapReduce優化方法:
    數據輸入
    Map階段
    Reducer階段
    I/O傳輸
    數據傾斜問題
    常用的調優參數
    
列舉幾個hadoop 生態圈的組件並做簡要描述    
    Zookeeper:是一個開源的分佈式應用程序協調服務,基於zookeeper 可以實現同步服務, 配置維護,命名服務。
    Flume:一個高可用的,高可靠的,分佈式的海量日誌採集、聚合和傳輸的系統。
    Hbase:是一個分佈式的、面向列的開源數據庫, 利用Hadoop HDFS 作爲其存儲系統。
    Hive:基於Hadoop 的一個數據倉庫工具,可以將結構化的數據檔映射爲一張數據庫表, 並提供簡單的sql 查詢功能,可以將sql 語句轉換爲MapReduce 任務進行運行。
    sqoop:
    
7. 簡要描述如何安裝配置apache 的一個開源Hadoop,只描述即可,無需列出具體步驟,列出具體步驟更好。
    1) 使用root 賬戶登錄
    2) 修改IP
    3) 修改host 主機名
    4) 配置SSH 免密碼登錄
    5) 關閉防火牆
    6) 安裝JDK
    7) 解壓hadoop 安裝包
    8) 配置hadoop 的核心文件hadoop-env.sh,core-site.xml , mapred-site.xml ,hdfs-site.xml,yarn-site.xml
    9) 配置hadoop 環境變量
    10)格式化hadoop namenode-format
    11)啓動節點start-all.sh
Hadoop 中需要哪些配置文件,其作用是什麼?
    1) core-site.xml:
        fs.defaultFS:hdfs://cluster1(域名),這裏的值指的是默認的HDFS 路徑。
        hadoop.tmp.dir:/export/data/hadoop_tmp,這裏的路徑默認是NameNode、DataNode、
        secondaryNamenode 等存放數據的公共目錄。用戶也可以自己單獨指定這三類節點的目錄。
        ha.zookeeper.quorum:hadoop101:2181,hadoop102:2181,hadoop103:2181,這裏是ZooKeeper 集羣的地址和端口。注意,數量一定是奇數,且不少於三個節點。
    2)hadoop-env.sh:
        只需設置jdk 的安裝路徑,如:export JAVA_HOME=/usr/local/jdk。
    3)hdfs-site.xml:
        dfs.replication:他決定着系統裏面的文件塊的數據備份個數,默認爲3 個。
        dfs.data.dir:datanode 節點存儲在文件系統的目錄。
        dfs.name.dir:是namenode 節點存儲hadoop 文件系統信息的本地系統路徑。
    4)mapred-site.xml:
        mapreduce.framework.name: yarn 指定mr 運行在yarn 上。

請列出正常工作的Hadoop 集羣中Hadoop 都分別需要啓動哪些進程,它們的作用分別是什麼?
    NameNode:它是hadoop 中的主服務器,管理文件系統名稱空間和對集羣中存儲的文件的訪問,保存有metadate。
    SecondaryNameNode 它不是namenode 的冗餘守護進程,而是提供週期檢查點和清理任務。幫助NN 合併editslog,減少NN 啓動時間。
    DataNode 它負責管理連接到節點的存儲(一個集羣中可以有多個節點)。每個存儲數據的節點運行一個datanode 守護進程。
    ResourceManager(JobTracker)JobTracker 負責調度DataNode 上的工作。每個DataNode 有一個TaskTracker,它們執行實際工作。
    NodeManager(TaskTracker)執行任務
    DFSZKFailoverController 高可用時它負責監控NN 的狀態,並及時的把狀態信息寫入ZK 。它
        通過一個獨立線程週期性的調用NN 上的一個特定接口來獲取NN 的健康狀態。FC 也有選擇誰作爲Active NN 的權利,因爲最多隻有兩個節點,目前選擇策略還比較簡單(先到先得,輪換)。
    JournalNode 高可用情況下存放namenode 的editlog 文件.
    
簡述Hadoop 的幾個默認端口及其含義
    dfs.namenode.http-address:50070
    SecondaryNameNode 輔助名稱節點端口號:50090
    dfs.datanode.address:50010端口
    fs.defaultFS:8020 或者9000
    yarn.resourcemanager.webapp.address:8088 資源job調度平臺

簡述hadoop實現Join的幾種方法:
    1、reduce side join
       reduce side join是一種最簡單的join方式,其主要思想如下:在map階段,map函數同時讀取兩個文件File1和File2,爲了區分兩種來源的key/value數據對,對每條數據打一個標籤(tag),比如:tag=0表示來自文件File1,tag=2表示來自文件File2。即:map階段的主要任務是對不同文件中的數據打標籤。在reduce階段,reduce函數獲取key相同的來自File1和File2文件的value list, 然後對於同一個key,對File1和File2中的數據進行join(笛卡爾乘積)。即:reduce階段進行實際的連接操作。
    2、map side join
       之所以存在reduce side join,是因爲在map階段不能獲取所有需要的join字段,即:同一個key對應的字段可能位於不同map中。Reduce side join是非常低效的,因爲shuffle階段要進行大量的數據傳輸。
       Map side join是針對以下場景進行的優化:兩個待連接表中,有一個表非常大,而另一個表非常小,以至於小表可以直接存放到內存中。這樣,我們可以將小表複製多份,讓每個map task內存中存在一份(比如存放到hash table中),然後只掃描大表:對於大表中的每一條記錄key/value,在hash table中查找是否有相同的key的記錄,如果有,則連接後輸出即可。
        爲了支持文件的複製,Hadoop提供了一個類DistributedCache,使用該類的方法如下:
       (1)用戶使用靜態方法DistributedCache.addCacheFile()指定要複製的文件,它的參數是文件的URI(如果是HDFS上的文件,可以這樣:hdfs://namenode:9000/home/XXX/file,其中9000是自己配置的NameNode端口號)。JobTracker在作業啓動之前會獲取這個URI列表,並將相應的文件拷貝到各個TaskTracker的本地磁盤上。
       (2)用戶使用DistributedCache.getLocalCacheFiles()方法獲取文件目錄,並使用標準的文件讀寫API讀取相應的文件。
       

請列出你所知道的hadoop調度器,並簡要說明其工作方法?
    比較流行的三種調度器有:默認調度器FIFO,計算能力調度器CapacityScheduler,公平調度器Fair Scheduler
    1) 默認調度器FIFO
        hadoop中默認的調度器,採用先進先出的原則
    2) 計算能力調度器CapacityScheduler
        選擇佔用資源小,優先級高的先執行
    3) 公平調度器FairScheduler
        同一隊列中的作業公平共享隊列中所有資源
    
簡答說一下hadoop的map-reduce編程模型
    首先map task會從本地文件系統讀取數據,轉換成key-value形式的鍵值對集合
    使用的是hadoop內置的數據類型,比如longwritable、text、bytesWritable等
    (inputFormat-->recordreader-->mapper-->partition-->sort(快排、如果自定義key的排序,則使用自定義的,默認TextWritable的)-->combiner(合併)-->spill溢寫
    -->reducer-->merger-->outputFormat-->RecordWriter)
    將鍵值對集合輸入mapper進行業務處理過程,將其轉換成需要的key-value在輸出
    之後會進行一個partition分區操作,默認使用的是hashpartitioner,可以通過重寫hashpartitioner的getpartition方法來自定義分區規則
    之後會對key進行進行sort排序,grouping分組操作將相同key的value合併分組輸出,在這裏可以使用自定義的數據類型,
    重寫WritableComparator的Comparator方法來自定義排序規則,重寫RawComparator的compara方法來自定義分組規則
    之後進行一個combiner歸約操作,其實就是一個本地段的reduce預處理,以減小後面shufle和reducer的工作量
    reduce task會通過網絡將各個數據收集進行reduce處理,最後將數據保存或者顯示,結束整個job
    
爲什麼要用flume導入hdfs,hdfs的構架是怎樣的
    flume可以實時的導入數據到hdfs中,當hdfs上的文件達到一個指定大小的時候會形成一個文件,或者超過指定時間的話也形成一個文件
    文件都是存儲在datanode上面的,namenode記錄着datanode的元數據信息,而namenode的元數據信息是存在內存中的,所以當文件切片很小或者很多的時候會卡死
    
map-reduce程序運行的時候會有什麼比較常見的問題?或者MapReduce 出現單點負載多大,怎麼負載平衡?(講訴數據傾斜的現象)
    比如說作業中大部分都完成了,但是總有幾個reduce一直在運行
    這是因爲這幾個reduce中的處理的數據要遠遠大於其他的reduce,可能是因爲對鍵值對任務劃分的不均勻造成的數據傾斜
    解決的方法可以在分區的時候重新定義分區規則對於value數據很多的key可以進行拆分、均勻打散等處理,或者是在map端的combiner中進行數據預處理的操作
    
Hive中存放是什麼?
    表。 
    存的是和hdfs的映射關係,hive是邏輯上的數據倉庫,實際操作的都是hdfs上的文件,HQL就是用sql語法來寫的mr程序。
    
Hive與關係型數據庫的關係?
    沒有關係,hive是數據倉庫,不能和數據庫一樣進行實時的CURD操作、也不支持事務型業務操作是一次寫入多次讀取的操作,可以看成是ETL工具。
    
Hadoop性能調優?
    調優可以通過系統配置、程序編寫和作業調度算法來進行。 
    hdfs的block.size可以調到128/256(網絡很好的情況下,默認爲64) 
    調優的大頭:mapred.map.tasks、mapred.reduce.tasks設置mr任務數(默認都是1) 
    mapred.tasktracker.map.tasks.maximum每臺機器上的最大map任務數 
    mapred.tasktracker.reduce.tasks.maximum每臺機器上的最大reduce任務數 
    mapred.reduce.slowstart.completed.maps配置reduce任務在map任務完成到百分之幾的時候開始進入 
    這個幾個參數要看實際節點的情況進行配置,reduce任務是在33%的時候完成copy,要在這之前完成map任務,(map可以提前完成) 
    mapred.compress.map.output,mapred.output.compress配置壓縮項,消耗cpu提升網絡和磁盤io 
    合理利用combiner 
    注意重用writable對象

Spark Streaming和Storm有何區別?
    一個實時毫秒一個準實時亞秒,不過storm的吞吐率比較低。

談談Hadoop序列化和反序列化及自定義bean對象實現序列化?

    1)序列化和反序列化
    (1)序列化就是把內存中的對象,轉換成字節序列(或其他數據傳輸協議)以便於存儲(持久化)和網絡傳輸。
    (2)反序列化就是將收到字節序列(或其他數據傳輸協議)或者是硬盤的持久化數據,轉換成內存中的對象。
    (3)Java的序列化是一個重量級序列化框架(Serializable),一個對象被序列化後,會附帶很多額外的信息(各種校驗信息,header,繼承體系等),不便於在網絡中高效傳輸。所以,hadoop自己開發了一套序列化機制(Writable),精簡、高效。
    2)自定義bean對象要想序列化傳輸步驟及注意事項:。
    (1)必須實現Writable接口
    (2)反序列化時,需要反射調用空參構造函數,所以必須有空參構造
    (3)重寫序列化方法
    (4)重寫反序列化方法
    (5)注意反序列化的順序和序列化的順序完全一致
    (6)要想把結果顯示在文件中,需要重寫toString(),且用"\t"分開,方便後續用
    (7)如果需要將自定義的bean放在key中傳輸,則還需要實現comparable接口,因爲mapreduce框中的shuffle過程一定會對key進行排序    

    
在一個運行的Hadoop 任務中,什麼是InputSplit?(☆☆☆☆☆)
    FileInputFormat源碼解析(input.getSplits(job))
    (1)找到你數據存儲的目錄。
    (2)開始遍歷處理(規劃切片)目錄下的每一個文件
    (3)遍歷第一個文件ss.txt
        a)獲取文件大小fs.sizeOf(ss.txt);
        b)計算切片大小computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
        c)默認情況下,切片大小=blocksize
        d)開始切,形成第1個切片:ss.txt—0:128M 第2個切片ss.txt—128:256M 第3個切片ss.txt—256M:300M(每次切片時,都要判斷切完剩下的部分是否大於塊的1.1倍,不大於1.1倍就劃分一塊切片)
        e)將切片信息寫到一個切片規劃文件中
        f)整個切片的核心過程在getSplit()方法中完成。
        g)數據切片只是在邏輯上對輸入數據進行分片,並不會再磁盤上將其切分成分片進行存儲。InputSplit只記錄了分片的元數據信息,比如起始位置、長度以及所在的節點列表等。
        h)注意:block是HDFS上物理上存儲的存儲的數據,切片是對數據邏輯上的劃分。
    (4)提交切片規劃文件到yarn上,yarn上的MrAppMaster就可以根據切片規劃文件計算開啓maptask個數。    
    
MapTask和ReduceTask工作機制(☆☆☆☆☆)
    (1)Read階段:Map Task通過用戶編寫的RecordReader,從輸入InputSplit中解析出一個個key/value。
    (2)Map階段:該節點主要是將解析出的key/value交給用戶編寫map()函數處理,併產生一系列新的key/value。
    (3)Collect收集階段:在用戶編寫map()函數中,當數據處理完成後,一般會調用OutputCollector.collect()輸出結果。在該函數內部,它會將生成的key/value分區(調用Partitioner),
        並寫入一個環形內存緩衝區中。
    (4)Spill階段:即“溢寫”,當環形緩衝區滿後,MapReduce會將數據寫到本地磁盤上,生成一個臨時文件。需要注意的是,將數據寫入本地磁盤之前,先要對數據進行一次本地排序,
        並在必要時對數據進行合併、壓縮等操作。
    (5)Combine階段:當所有數據處理完成後,MapTask對所有臨時文件進行一次合併,以確保最終只會生成一個數據文件。
    (1)Copy階段:ReduceTask從各個MapTask上遠程拷貝一片數據,並針對某一片數據,如果其大小超過一定閾值,則寫到磁盤上,否則直接放到內存中。
    (2)Merge階段:在遠程拷貝數據的同時,ReduceTask啓動了兩個後臺線程對內存和磁盤上的文件進行合併,以防止內存使用過多或磁盤上文件過多。
    (3)Sort階段:按照MapReduce語義,用戶編寫reduce()函數輸入數據是按key進行聚集的一組數據。爲了將key相同的數據聚在一起,Hadoop採用了基於排序的策略。
        由於各個MapTask已經實現對自己的處理結果進行了局部排序,因此,ReduceTask只需對所有數據進行一次歸併排序即可。
    (4)Reduce階段:reduce()函數將計算結果寫到HDFS上。
    
描述mapReduce中shuffle階段的工作流程,如何優化shuffle階段(☆☆☆☆☆)
    分區,排序,溢寫,拷貝到對應reduce機器上,增加combiner,壓縮溢寫的文件。

描述mapReduce中combiner的作用是什麼,一般使用情景,哪些情況不需要,及和reduce的區別?
    1)Combiner的意義就是對每一個maptask的輸出進行局部彙總,以減小網絡傳輸量。
    2)Combiner能夠應用的前提是不能影響最終的業務邏輯,而且,Combiner的輸出kv應該跟reducer的輸入kv類型要對應起來。
    3)Combiner和reducer的區別在於運行的位置。
        Combiner是在每一個maptask所在的節點運行;
        Reducer是接收全局所有Mapper的輸出結果。
    
MapReduce 怎麼實現 TopN? (☆☆☆☆☆)
    可以自定義groupingcomparator,對結果進行最大值排序,然後再reduce輸出時,控制只輸出前n個數。就達到了topn輸出的目的。
    
Hadoop的緩存機制(Distributedcache)(☆☆☆☆☆)
        分佈式緩存一個最重要的應用就是在進行join操作的時候,如果一個表很大,另一個表很小,我們就可以將這個小表進行廣播處理,即每個計算節點上都存一份,
        然後進行map端的連接操作,經過我的實驗驗證,這種情況下處理效率大大高於一般的reduce端join,廣播處理就運用到了分佈式緩存的技術。
        DistributedCache將拷貝緩存的文件到Slave節點在任何Job在節點上執行之前,文件在每個Job中只會被拷貝一次,緩存的歸檔文件會被在Slave節點中解壓縮。
        將本地文件複製到HDFS中去,接着Client會通過addCacheFile()和addCacheArchive()方法告訴DistributedCache在HDFS中的位置。當文件存放到文地時,
        JobClient同樣獲得DistributedCache來創建符號鏈接,其形式爲文件的URI加fragment標識。當用戶需要獲得緩存中所有有效文件的列表時,
        JobConf 的方法 getLocalCacheFiles() 和getLocalArchives()都返回一個指向本地文件路徑對象數組。

什麼樣的計算不能用mr來提速?
    1)數據量很小。
    2)繁雜的小文件。
    3)索引是更好的存取機制的時候。
    4)事務處理。
    5)只有一臺機器的時候。
    
HDFS的存儲機制(☆☆☆☆☆)
    HDFS寫數據過程
        1)客戶端通過Distributed FileSystem模塊向NameNode請求上傳文件,NameNode檢查目標文件是否已存在,父目錄是否存在。
        2)NameNode返回是否可以上傳。
        3)客戶端請求第一個 block上傳到哪幾個datanode服務器上。
        4)NameNode返回3個datanode節點,分別爲dn1、dn2、dn3。
        5)客戶端通過FSDataOutputStream模塊請求dn1上傳數據,dn1收到請求會繼續調用dn2,然後dn2調用dn3,將這個通信管道建立完成。
        6)dn1、dn2、dn3逐級應答客戶端。
        7)客戶端開始往dn1上傳第一個block(先從磁盤讀取數據放到一個本地內存緩存),以packet爲單位,dn1收到一個packet就會傳給dn2,dn2傳給dn3;
            dn1每傳一個packet會放入一個應答隊列等待應答。
        8)當一個block傳輸完成之後,客戶端再次請求NameNode上傳第二個block的服務器。(重複執行3-7步)。
    HDFS讀數據過程
        1)客戶端通過Distributed FileSystem向NameNode請求下載文件,NameNode通過查詢元數據,找到文件塊所在的DataNode地址。
        2)挑選一臺DataNode(就近原則,然後隨機)服務器,請求讀取數據。
        3)DataNode開始傳輸數據給客戶端(從磁盤裏面讀取數據輸入流,以packet爲單位來做校驗)。
        4)客戶端以packet爲單位接收,先在本地緩存,然後寫入目標文件。
    
secondary namenode工作機制(☆☆☆☆☆)
    1)第一階段:NameNode啓動
    (1)第一次啓動NameNode格式化後,創建fsimage和edits文件。如果不是第一次啓動,直接加載編輯日誌和鏡像文件到內存。
    (2)客戶端對元數據進行增刪改的請求。
    (3)NameNode記錄操作日誌,更新滾動日誌。
    (4)NameNode在內存中對數據進行增刪改查。
    2)第二階段:Secondary NameNode工作
    (1)Secondary NameNode詢問NameNode是否需要checkpoint。直接帶回NameNode是否檢查結果。
    (2)Secondary NameNode請求執行checkpoint。
    (3)NameNode滾動正在寫的edits日誌。
    (4)將滾動前的編輯日誌和鏡像文件拷貝到Secondary NameNode。
    (5)Secondary NameNode加載編輯日誌和鏡像文件到內存,併合並。
    (6)生成新的鏡像文件fsimage.chkpoint。
    (7)拷貝fsimage.chkpoint到NameNode。
    (8)NameNode將fsimage.chkpoint重新命名成fsimage。
    checkPoint檢查點時間設置:
            1:通常情況下每隔1小時執行一次
            2:一分鐘檢查一次操作次數,當操作次數達到1百萬時,SecondaryNameNode執行一次
    
NameNode與SecondaryNameNode 的區別與聯繫?(☆☆☆☆☆)
    1)區別
    (1)NameNode負責管理整個文件系統的元數據,以及每一個路徑(文件)所對應的數據塊信息。
    (2)SecondaryNameNode主要用於定期合併命名空間鏡像和命名空間鏡像的編輯日誌。
    2)聯繫:
    (1)SecondaryNameNode中保存了一份和namenode一致的鏡像文件(fsimage)和編輯日誌(edits)。
    (2)在主namenode發生故障時(假設沒有及時備份數據),可以從SecondaryNameNode恢復數據。
    
HAnamenode 是如何工作的? (☆☆☆☆☆)
    ZKFailoverController主要職責
    1)健康監測:週期性的向它監控的NN發送健康探測命令,從而來確定某個NameNode是否處於健康狀態,如果機器宕機,心跳失敗,那麼zkfc就會標記它處於一個不健康的狀態。
    2)會話管理:如果NN是健康的,zkfc就會在zookeeper中保持一個打開的會話,如果NameNode同時還是Active狀態的,那麼zkfc還會在Zookeeper中佔有一個類型爲短暫類型的znode,
       當這個NN掛掉時,這個znode將會被刪除,然後備用的NN,將會得到這把鎖,升級爲主NN,同時標記狀態爲Active。
    3)當宕機的NN新啓動時,它會再次註冊zookeper,發現已經有znode鎖了,便會自動變爲Standby狀態,如此往復循環,保證高可靠,需要注意,目前僅僅支持最多配置2個NN。
    4)master選舉:如上所述,通過在zookeeper中維持一個短暫類型的znode,來實現搶佔式的鎖機制,從而判斷那個NameNode爲Active狀態
    
Namenode故障處理方法
    Namenode故障後,可以採用如下兩種方法恢復數據。
        方法一:將SecondaryNameNode中數據拷貝到namenode存儲數據的目錄;
        方法二:使用-importCheckpoint選項啓動namenode守護進程,從而將SecondaryNameNode中數據拷貝到namenode目錄中。
        5.8.1 手動拷貝SecondaryNameNode數據:
            模擬namenode故障,並採用方法一,恢復namenode數據
            1)kill -9 namenode進程
            2)刪除namenode存儲的數據(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)
            [atguigu@hadoop102 hadoop-2.7.2]$ rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*
            3)拷貝SecondaryNameNode中數據到原namenode存儲數據目錄
            [atguigu@hadoop102 dfs]$ scp -r atguigu@hadoop104:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/* ./name/
            4)重新啓動namenode
            [atguigu@hadoop102 hadoop-2.7.2]$ sbin/hadoop-daemon.sh start namenode
            
        5.8.2 採用importCheckpoint命令拷貝SecondaryNameNode數據
            模擬namenode故障,並採用方法二,恢復namenode數據
            0)修改hdfs-site.xml中的
            <property>
              <name>dfs.namenode.checkpoint.period</name>
              <value>120</value>
            </property>

            <property>
              <name>dfs.namenode.name.dir</name>
              <value>/opt/module/hadoop-2.7.2/data/tmp/dfs/name</value>
            </property>
            1)kill -9 namenode進程
            2)刪除namenode存儲的數據(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)
            [atguigu@hadoop102 hadoop-2.7.2]$ rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*
            3)如果SecondaryNameNode不和Namenode在一個主機節點上,需要將SecondaryNameNode存儲數據的目錄拷貝到Namenode存儲數據的平級目錄,並刪除in_use.lock文件。
            [atguigu@hadoop102 dfs]$ scp -r atguigu@hadoop104:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary ./
            [atguigu@hadoop102 namesecondary]$ rm -rf in_use.lock
            [atguigu@hadoop102 dfs]$ pwd
            /opt/module/hadoop-2.7.2/data/tmp/dfs
            [atguigu@hadoop102 dfs]$ ls
            data  name  namesecondary
            4)導入檢查點數據(等待一會ctrl+c結束掉)
            [atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs namenode -importCheckpoint
            5)啓動namenode
            [atguigu@hadoop102 hadoop-2.7.2]$ sbin/hadoop-daemon.sh start namenode

文件格式:SequenceFile
------------------
    1.SequenceFile
        Key-Value對方式。

    2.不是文本文件,是二進制文件。

    3.可切割
        因爲有同步點。
        reader.sync(pos);    //定位到pos之後的第一個同步點。
        writer.sync();        //寫入同步點

    4.壓縮方式
        不壓縮
        record壓縮            //只壓縮value
        塊壓縮                //按照多個record形成一個block.


文件格式:MapFile
--------------------
    1.Key-value
    2.key按升序寫入(可重複)。
    3.mapFile對應一個目錄,目錄下有index和data文件,都是序列文件。
    4.index文件劃分key區間,用於快速定位。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章