Hadoop HDFS和MapReduce

先思考問題

我們處在一個大數據的時代已經是不爭的事實,這主要表現在數據源多且大,如互聯網數據,人們也認識到數據里往往隱藏著規律或模式,能夠帶來巨大的商業價值。其中最為人們所津津樂道的案例就是沃爾瑪將啤酒和紙尿褲搭配銷售的案例。

現在往往不缺少數據,但是面對海量數據勢必要求有高效安全的存儲海量數據的方案,有了數據后要發現其中隱藏的價值就需要分析數據,因此,存儲和分析是大數據工具所需要解決的主要問題。

目前,機器的存儲能力在不斷的增長,但是讀取速度卻相形見絀。最容易想到的提高讀取效率的方法是多磁盤并行讀取,就像RAID陣列一樣。多磁盤協同存儲所要解決的第一個問題就是硬件失效問題,常用的方法就是狡兔三窟-復制,另外一個問題就是分析任務需要從多個存儲設備中讀取數據,如何協同的做好這些事情是一個不小的挑戰。

Hadoop正是為解決存儲和分析問題而生,Hadoop的HDFS提供了一種安全可靠的分布式文件存儲系統,并提供了基于批處理模式的MapReduce數據分析框架。

那么,存儲和分析的問題為什么就不能用我么所熟悉的RDBMS來處理呢?

在存儲上,RDBMS適合結構化數據的存儲,且保證數據的完整性等約束,而HDFS適合存儲非結構化或半結構化數據,并不對數據進行完整性約束。且HDFS本身是以分布式方式存儲海量數據而做為己任,在存儲的可擴展能力具備線性增長能力。在分析上,RDBMS的B樹索引結構適合小范圍更新和點查,MapReduce適合一次存儲多次即席查詢,適合需要批處理的方式讀取整個數據塊來做線下分析場景。在其他方面,RDBMS承擔著數據操作事務控制等責任,HDFS并不存在事務的特性。

簡介

Hadoop的作者是Doug Cutting,Lucene的作者。該項目起源于一個web搜索引擎項目Nutch,這個項目是Lucene的一部分。當時項目正需要一個強大的分布式文件系統來管理從網絡上抓取的海量數據,而此時google發表了GFS的論文,因此團隊就以GFS論文而開發并將其開源。

Hadoop這個名字是編造的,作者的孩子給一個黃色的布料玩具小象起的名字。

Hadoop這個詞在狹義上指HDFS和MapReduce,廣義上來講是Hadoop生態,包含了很多和分布式計算以及數據處理的工程。了解Hadoop最重要的是要理解HDFS和MapReduce。

HDFS

概念

DFS即分布式文件系統,分布式文件存儲在多個機器組成的集群中,用來管理分布式文件存儲的系統稱之為分布式文件系統。

HDFS即Hadoop分布式文件系統,它擅長存儲大文件,流式讀取,運行于一般性的商業硬件上。HDFS不適合存儲大量的小文件,namenode會在內存中存儲元數據,通常情況下每個文件、目錄和塊都將占用150個字節;也不適合任意并發寫的場景,HDFS的寫文件操作是append的模式。

基礎中的基礎

在HDFS中,文件被分割成不同的塊存儲在集群的數據節點里,文件系統的元數據由文件系統集中管理。

  • block

    文件系統的塊通常是512字節,但是HDFS默認128M,但是和普通的文件系統相比,如果一個文件沒有達到128M,其并不會占滿整個塊。塊默認如此大是為了減少尋址時間。抽象出塊的概念的好處在于一個文件的大小可以超過整個磁盤,簡化存儲管理,很適合復制機制來實現高可用。

  • namenode和datanode

    namenode管理文件系統的命名空間,維護文件系統樹、所有文件、目錄以及塊的元數據,元數據有兩種namespace image和edit log。

    namenode擁有block和datanode之間的映射關系,但是它并不持久化這些信息,這些信息來源依賴于datanode啟動時向namenode發送的報告。

    datanode維護著最終的block,并定期向namenode發送該datanode包含的block列表。

  • datanode的選取策略

    HDFS的塊采用復制機制做到數據高可用,默認情況下塊副本一共是三個。namenode在選取副本存儲的datanode節點時,平衡穩定性和讀寫帶寬后遵循一定的策略。Hadoop的策略是第一個副本放在和客戶端程序同個節點上,如果客戶端不在集群里,該數據節點將隨機選取,當然也會有其他常規檢查,如不會選擇非常忙碌的機器。第二個副本放在另一個不同的機架的數據節點,第三個副本放在和第二個副本同機架的不同節點上。如果有更多的副本,其他的就隨機放入集群的節點,但是也會避免太多的副本放在同一個機架上。

了解下可用性相關

namenode的抗失效能力很重要,一種方法是備份元數據文件,Hadoop提供相關配置,可以使namenode的持久化狀態存儲于多個文件系統,比如本地磁盤或NFS。另一種方式是啟動secondary namenode,它定期的將namespace image和edit log合并,但是它畢竟和主namenode存在狀態差,所以主namenode失效后,經常存在丟失數據的問題。這種情況下,一般會拷貝主namenode的元數據文件到secondary namenode,并使其成為主namenode。

  • HDFS聯邦

    HDFS聯邦通過一組namenode合作,每個namenode管理不同的命名空間,且不相互依賴。但是block池的信息并不進行分區,datanode要向每個namenode報告block信息。

  • HDFS HA

    備份元數據以及secondary namenode用來低于數據丟失,但是并不能達到高可用的狀態。

    要從一個失效的namenode中恢復,管理員需要啟動一個新的namenode應用備份的元數據,并配置datanode和相關客戶端使用新的namenode。新的namenode需要加載完namespace image,重做edit log,接收到足夠的block報告,才能對外正常提供服務。

    為了實現HA,

    1. 所有namenode必須采用高可用的共享存儲來共享edit log。
    2. datanode發送block報告給所有namenode。
    3. 客戶端程序需要處理namenode實現的場景,客戶端對失效轉移的處理是透明的,由客戶端的相關庫實現
    4. secondary namenode作為備用,定期從主namenode獲取命名空間

    一旦發生失效,管理員可以通過冷啟動的方式激活備用。

  • 失效轉移

    采用ZooKeeper維持一個轉移序列來保證只有一個namenode處于激活狀態。HA要確保前一個激活的namenode不會做出沖突的破壞活動,QJM只允許一次只有一個namenode寫edit log。然是仍然可能存在前一個激活的namenode向某個客戶端請求提供著過時的服務,最好是設置一個ssh命令來殺死那個namenode進程。

Hadoop文件系統

Hadoop對文件系統進行了抽象:org.apache.hadoop.fs.FileSystem代表Hadoop文件系統,并提供一些具體的實現。例如:本地文件系統和HDFS,

Filesystem URI scheme Java Implementation
Local file fs.LocalFileSystem
HDFS hdfs hdfs.DistributedFileSystem
-- -- --

Java接口

讀取數據

獲取FileSystem實例的靜態工程方法:

public static FileSystem get(Configuration conf);
public static FileSystem get(URI uri,Configuration conf);
public static FileSystem get(URI uri,Configuration conf,String user);

configuration對象封裝了classpath下的配置文件,例如etc/hadoop/core-site.xml。文件系統類型是由URI scheme決定,或者由core-site.xml的配置決定(如果沒有指定便默認本地文件系統)。第三個方法是作為某個用戶去獲取FileSystem實例。

通過open方法來獲取一個文件的輸入流:

public FSDataInputStream open(Path f);

例如:

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(uri),conf);
InputStream in = fs.open(new Path(uri));

FSDataInputStream繼承java.io.DataInputStream并實現了Seekable,所以它支持讀取流的任何位置。

void seek(long pos);
long getPos();

FSDataInputStream也實現了PositionedReadable,可以做到在給定位置讀取內容。

int read(long position,byte[] buffer,int offset,int length)
int readFully(long position,byte[] buffer,int offset,int length)
int readFully(long position,byte[] buffer)

read方法實現了在position位置讀取length長度的字節,并存入buffer的offset為位置。

readFull從buffer中讀取length長度的字節,或者全部字節(如果沒有指定length)。

寫數據

FileSystem提供創建文件的方法:

public FSDataOutputStream create(Path f)

也可以利用帶Progressable參數的方法,這樣應用程序就會得到進度通知。默認每向管線存儲64KB的數據將會通知一次。

public FSDataOutputStream create(Path f,Progressable p)
public interface Progressable{
    public void progress();
}

另一種方案是在現有的文件基礎上累加內容:

public FSDataOutputStream append(Path f)

FSDataOutputStream有個方法來獲取當前位置

public long getPos();

最后,FileSystem提供了創建目錄的操作

public boolean mkdirs(Path f)

如果父目錄不存在,將自動創建。

查詢文件
  • FileStatus

    FileStatus封裝了文件的元數據。FileSystem提供如下方法

    public FileStatus getFileStatus(Path f)
    

    FileStatus提供很多有用的方法:

    getPath
    isDirectory
    getLen
    getModificationTime
    getReplication
    getBlockSize
    getOwner
    getGroup
    getPermission
    
  • 文件列

    FileSystem提供了一些方法獲取文件列表:

    FileStatus[] listStatus(Path f)
    FileStatus[] listStatus(Path f,PathFilter filter)
    FileStatus[] listStatus(Path[] files)
    FileStatus[] listStatus(Path[] files,PathFilter filter)
    
  • 文件模式

    有兩個方法可以通過通配符來匹配多個文件

    FileStatus[] globStatus(Path pathPattern)
    FileStatus[] globStatus(Path pathPattern,PathFilter filter)
    

    Hadoop支持Unix bash shell的glob字符集。

  • 路徑過濾

    public interface PathFilter{
      boolean accept(Path path)
    }
    
刪除數據

如下方法提供刪除文件或目錄

boolean delete(Path f,boolean recursive)

讀寫工作流

  • 讀文件

    在namenode的指引下,客戶端程序找到每個數據塊的最佳datanode,然后直接和其聯系讀取數據。

5.png
  1. 客戶端調用FileSystem,此處為分布式文件系統DistributedFileSystem.open方法
  2. DistributedFileSystem向namenode獲取第一批塊的位置,namenode返回包含塊拷貝的datanode地址,并按著和客戶端的就近原則進行排序
  3. DistributedFileSystem返回FSDataInputStream實例,該實例負責和datanode間的IO。
  4. 客戶端調用流的read方法
  5. FSDataInputStream聯系連接最近的datanode,數據從datanode傳回客戶端
  6. 當塊讀取完后,FSDataInputStream關閉和該datanode的連接,并為下個塊連接最佳的datanode,這個過程對客戶端來說是透明的
  7. 如果需要,文件系統將向namenode獲取下一批塊的位置
  8. 客戶端調用close方法結束讀取
  • 寫文件
6.png
  1. 客戶端調用DistributedFileSystem的write方法。
  2. DistributedFileSystem請求namenode創建一個新文件。namenode做一些常規檢查,如是否已經存在同名文件,是否有權限創建。
  3. DistributedFileSystem返回一個FSDataOutputStream實例用于寫數據
  4. 客戶端寫數據,FSDataOutputStream對數據進行分包,并將數據包放入data隊列
  5. DataStreamer要求namenode分配新的塊,這些塊會被namenode分配一些用于存放拷貝的datanode。這些datanode組成一個管線,第一個datanode存儲每個包,并將其傳送到第二個datanode,后面依次相似。
  6. ack隊列維護著等待datanode確認的分包,一個分包只有在收到管線中所有datanode的確認后才會移除。
  7. 調用close方法,完成寫入。
  8. close方法flush所有分包,并等待確認,最后通知namenode告知文件創建完成。

MapReduce

感受MapReduce程序

MapReduce是Hadoop下的數據處理編程模型,運行于基于yarn架構的MapReduce框架中。下面通過一個例子來感受下MapReduce。該例子出自《Hadoop The Definitive Guide》第四版的關于氣象數據的例子,目前第四版沒有中文版,有能力的話可以看看這本書。

準備數據

原始數據是一些的tar文件,每年的氣象數據都在一個單獨的tar文件里。每個tar文件包含若干zip文件,每個zip文件是不同氣象站當年的氣象數據。類似2009.tar,其下包含氣象站1.gz、氣象站n.gz,其中每條氣象數據占一行,這種結構。

Hadoop善于處理大文件,所以作者將文件解壓,然后按年合并成單獨的文件。

自己寫個程序

如果讓我們來實現一個程序用來計算每年的最大溫度怎么辦?可能會類似如下偽代碼:

for(year:all){
    InputStream in = readFile(year); //讀取每年的文件
    String line;
    float max;
    while(line = in.readLine()!=null){
        float tmp =  在line固定區間讀取溫度值;
        if(tmp>max){
          max = tmp;
        }
    }
    print(year,max);
}

為了加快處理速度,最好是能并行處理這些數據文件,比如按年分給不同的進程去處理。但是這會有一些問題,給每個進程分配均等的任務量不是件容易的事情,每年的數據量可能大相徑庭,按木桶原理,任務的處理速度取決于最慢的那個進程也就是處理氣象數據文件最大的那個進程。

那么最好的方式就是將文件分成相同大小的塊,每個塊都由不同的進程去處理。這樣,每個進程處理不同的塊,計算當前塊范圍內的溫度最大值,形成中間結果。要得到最終結果,接下來需要把這些中間結果再匯集起來,求出最終的最大值,這就是mapreduce框架要的事情。

MapReduce程序

MapReduce程序運行分為兩個階段,map和reduce。每個階段都由key-value這種形式的數據做為輸入輸出,具體的數據類型由編程者決定,編程者并未這兩個階段分別指定map函數和reduce函數。

在map階段,map函數接收原始數據,在該例中選擇文本類型的格式,這種格式會自動將一行的文本內容作為value,文本內容在文件中的偏移量作為key,一般情況下代表偏移量的key對我們來說沒有太大用處。map函數讀取文本內容,讀取出年并作為key,讀取溫度值作為value,輸出給mapreduce框架。

mapreduce框架拿到map階段的輸出結果后,按key分組并排序,這樣每一年對應一組溫度值,然后將分組排序后的結果按key傳給reduce,進入reduce階段。

reduce函數遍歷傳來的value集合,計算最大值,以傳入的key也就是年作為key,最大值作為value進行輸出。如下圖所示:

1.png

java實現

實現mapreduce程序需要實現三個主要部件,mapper、reducer和一個用來啟動job的main程序。

Hadoop提供了抽象的Mapper類,具有四個泛型參數,用來指定輸入key、輸入value、輸出key、輸出value的類型。

    public class MaxTemperatureMapper extends Mapper
    <LongWritable,Text,Text,IntWritable>{
        public void map(LongWritable key,Text value,Context context){
            String line = value.toString();
            String year = line.substring(15,19);
            int airTemperature;
            ......
            context.write(new Text(year),new IntWritable(airTemperature))
        }
    }

map方法有三個參數,分別代表輸入key,輸入value,上下文對象。通過上下文對象輸出map階段的分析結果。

同樣的,Hadoop提供了抽象的Reducer類,具有四個參數,指定了reducer階段的輸入輸出類型。

    public class MaxTemperatureReducer extends Reducer
    <Text,IntWritable,Text,IntWritable>{
        public void reduce(Text key,Iterable<IntWritable> values,Context context){
            int maxValue=Integer.MIN_VALUE;
            for(IntWritable v:values){
                ......
            }
            context.write(key,new IntWritable(maxValue));
        }
    }

最后,需要開發一個main函數來運行job。

    public class MaxTemperature{
        public static void main(String[] args){
            Job job = new Job();
            job.setJarByClass(MaxTemperature.class);
            job.setJobName("Max Temperature");
            
            FileInputFormate.addInputPath(job,new Path(args[0]));
            FileOutputFormate.setOutputPath(job,new Path(args[1]));
            
            job.setMapperClass(MaxTemperatureMapper.class);
            job.setReducerClass(MaxTemperatureReducer.class);
            
            job.setOutputKeyClass(Text.class);
            job.setOutputValueClass(IntWritable.class);
            
            System.exit(job.waitForCompletion(true)?0:1);       
        }
    }

運行這個job時需要將代碼打包成jar包,在一個分布式模式的hadoop中運行時,jar包會在集群中傳遞,以便在目標機器運行。setJarByClass告訴hadoop根據class找到相關的jar包,但也可以在運行時直接指定jar包。

輸入路徑可以是文件或文件夾或模式匹配的路徑,但輸出輸出路徑必須是一個文件夾,且在運行job之前該文件夾不存在。setMapperClass和setReducerClass指定mapper和reducer,setOutputKeyClass和setOutputValueClass指定reducer的輸出類型,該類型必須和reducer類型中聲明的類型一致,mapper的輸出類型默認和此一致,所以不用設置。否則,通過setMapOutputKeyClass和setMapOutputValueClass來設置。

輸入類型會默認為TextInputFormat,否則通過setInputFormateClass設置。

waitForCompletion用來提交job,true使用來指定是否打印調試信息。返回true代表執行成功,否則執行失敗。

運行

將程序打成jar包,通過命令行運行

MapReduce任務工作原理

MapReduce任務的工作過程如下圖所示:

4.png

整個過程設計5個組件:客戶端、YARN資源管理器、YARN節點管理器、MapReduce application master、HDFS

  • 客戶端程序通常是MapReduce驅動程序提交一個任務
  • YARN資源管理器統一協調集群的計算資源
  • YARN節點管理器啟動和監控機器上的容器
  • MapReduce application master為job協調各task的運行。application master和MapReduce task都運行在集群中的某機器中的具體容器中,這些容器都受YARN資源管理器調度并被具體節點管理器管理。
  • HDFS用于在組件間共享job相關的文件

job的提交

job提交的過程如下:

  • 向資源管理器詢問新的應用ID用做job的ID
  • 檢查輸出路徑設置是否規范,比如沒有指定或者已經存在,將會報錯
  • 為job計算輸入分片,如果無法為jbo計算出輸入分片,比如指定的輸入路徑不存在,也將會報錯
  • 拷貝job所需要的資源,包括運行job的jar文件,配置文件,為其計算出的輸入分片都將拷貝到共享文件系統中以job ID命名的文件夾中
  • 向資源管理器提交任務

job的初始化

資源管理器接到提交job請求時,YARN調度器啟動一個容器用于運行application master(step 5)。

MapReduce job的application master是一個java應用程序,其主要類是MRAppMaster。MRAppMater做一些初始化的工作,如創建一些用來來接收task的進度報告的對象,用以跟蹤整個job的進度(step6)。

接收共享文件系統中的輸入分片(step7)。為每個輸入分片創建一個map task,根據配置創建若干reduce task。application master必須決定如何運行這些task,如果job非常小,它可以選擇和這些task運行于同一個jvm中。默認的,少于10個mapper,只有一個reducer,輸入大小少于一個HDFS block的job被認定為是一個小作業。application master會任務這樣的job如果并行的運行于不同的容器中,弊大于利。不如將這些task運行于同一個節點串行的運行。這樣的job會被稱為一個uber task。

task的分配

如果job不是被認定為是一個uber task,application master會為各個map和reduce task向資源管理器申請容器(step 8)。map task的請求優先于reduce task,且在map task完成5%之前,不會創建reduce task的請求。

reduce task可以運行于集群的任何地方,但是map task必須受數據本地化的約束,最佳的場景是map task要運行于分片所在的節點,稱之為數據本地化,其次,是運行于和分片數據處于同一機架的節點中,這稱之為機架本地化,如果數據本地化和機架本地化都無法滿足,只能跨機架完成任務了。

請求可以附加對資源的要求,如內存和CPU的需求,默認情況下,每個map和reduce task分配1024MB內存和一核。

task的執行

資源管理器給一個task分配資源(該資源是在某個節點的用于運行一個容器的資源),application master聯系對應的node manager,啟動容器(step 9)。

task被一個java應用來運行,其主類YarnChild,在其運行任務前,其先定位任務所需的所有資源,包括job配置、jar文件(step 10)。

運行任務(step 11)。

狀態更新

每個job以及每個task都有一個status,包括狀態,如running,successfully completed,failed,map和reduce的進度。每個task定時(默認一秒)向application master匯報自己的進度,對于map task,進度就是其處理的輸入百分比,對于reduce task,就需要估算。

失效處理

task失效

最常見的失效情況是task代碼里拋出了運行時異常,執行task的jvm在其退出之前向application master報告錯誤,application master會標記該task是失敗狀態,釋放對應的容器,該容器所占用的資源會被其他task所利用。

類似jvm突然停止工作的異常,node manager會通知application master執行task的jvm進程退出了,task也將被application master置為失敗狀態。

對于掛起狀態的task通過超時來處理,application master在很久沒有收到task的進度更新后,會將其置為失效,超時時間可以設置。當然也可以設置為永不超時。

application master將重新調度失敗的task,重新調度將避免選擇先前失效時所在的node manager。默認情況下,一個task失敗達到4次,該task不再嘗試執行,job也將失敗。對于一些不希望task失敗就直接導致job失敗的應用來說,需要設置一個參數來控制task失效在某百分比以內時不會觸發job失敗。

task可能會被殺死,這種狀況有別于失敗,例如node manager在失效狀態下,運行其中的所有task都將被殺死,當然用戶也可以自己通過工具將其殺死,被殺死的task,不計入嘗試次數范圍。

application master失效

MapReduce application master的默認失敗嘗試次數是2,所以達到2次時就認為job失敗,也可以自行設置。Yarn框架也提供了application master的最大嘗試次數,同時默認也是2。

application master定期向resource manager發送心跳,resource manager一旦檢測到application master失敗,就會在一個新的容器中啟動新的application master實例。在這種狀況下,MapReduce application master使用job的執行歷史來恢復task的運行狀態,已經運行的不會再重新運行

MapReduce客戶端會不斷從application master那里獲取job的進度,application master失效后,客戶端將自動重新定位到新的application master。

node manager失效

node manager定期向resource manager發送心跳,默認超時為10分鐘。一旦失效,將被移出節點池。任何運行于失效node manager所在機器上的task或application master都將得到恢復。

如果一個應用在某node manager 上發生失敗過多,該node manager將被application master加入黑名單,(資源管理器并不跨應用維護黑名單,所以新job的task可能會運行于一個被某application master列入黑名單的節點)即使其本身并沒有失效。如果超過三個task失敗,MapReduce application master將在不同的節點上重新調度task。

resource manager失效

resource manager一旦失效,job以及task容器無法啟動,是一件很嚴重的故障,所以很有必要做HA。應用的信息被存儲在HA的狀態存儲中(ZooKeeper或HDFS)。

新的resource manager啟動時,從狀態存儲中讀取應用的信息,重啟application master.

客戶端和node manager必須處理resource manager失效問題,因為可能和兩個resource manager交互。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內容

  • 首先,我們在使用前先看看HDFS是什麼?這將有助于我們是以后的運維使用和故障排除思路的獲得。 HDFS采用mast...
    W_Bousquet閱讀 4,216評論 0 2
  • 摘自:http://staticor.io/post/hadoop/2016-01-23hadoop-defini...
    wangliang938閱讀 602評論 0 1
  • 之前的有點忘記了,這里在云筆記拿出來再玩玩.看不懂的可以留言 大家可以嘗試下Ambari來配置Hadoop的相關環...
    HT_Jonson閱讀 2,979評論 0 50
  • HDFS的設計目標 通過上一篇文章的介紹我們已經了解到HDFS到底是怎樣的東西,以及它是怎樣通過多副本機制來提供高...
    陌上疏影涼閱讀 1,452評論 0 3
  • 隨著年齡的增長,對過年過節,提早不會去渴望,其間也不是欣喜若狂。來了,就準備好一切,平平靜靜的過,該做做,該吃...
    云上畫文閱讀 194評論 0 0