Hadoop入門(mén)|HDFS分布式文件系統(tǒng)

寫(xiě)在前面

我自己一直比較喜歡大數(shù)據(jù)這個(gè)方向的工作,雖然自己也在大數(shù)據(jù)相關(guān)的崗位上工作了小兩年坛怪,但一直沒(méi)有系統(tǒng)的學(xué)習(xí)過(guò)大數(shù)據(jù)相關(guān)的知識(shí)申眼。

說(shuō)到自身經(jīng)歷,可能和大部分程序員一樣潮饱,一直混跡于小公司来氧,我從第一家公司離職的理由就是拖欠工資,那個(gè)時(shí)候又是剛畢業(yè)饼齿,手里沒(méi)有一點(diǎn)積蓄饲漾,后來(lái)實(shí)在沒(méi)辦法只能離職求活路。不過(guò)很感謝第一家公司缕溉,在那是我進(jìn)步最快的地方考传,我從事大數(shù)據(jù)崗位也是那家公司花錢(qián)讓我去學(xué)習(xí)的。除了是小公司证鸥,其他的都很好僚楞,技術(shù)氛圍很棒!第二家公司雖然比較大枉层,但是屬于項(xiàng)目外包型公司(雖然我所在的部門(mén)屬于自研型泉褐,但還是外包的干法,我依舊記得我入職之后才發(fā)現(xiàn)公司代碼沒(méi)有版本管理鸟蜡,所有代碼都在主分支上膜赃,沒(méi)有一份技術(shù)文檔,全靠口口相傳)揉忘。

今年疫情原因跳座,各個(gè)行業(yè)裁員的裁員端铛,降薪的降薪,我在的公司也不例外疲眷,全員降薪30%禾蚕,然而周末也沒(méi)了,瘋狂趕項(xiàng)目進(jìn)度狂丝,我最多的時(shí)候同時(shí)支持了五個(gè)項(xiàng)目組的報(bào)表開(kāi)發(fā)换淆,每天做夢(mèng)都?jí)粢?jiàn)自己在催著改報(bào)表。

更恐怖的是開(kāi)發(fā)這個(gè)行業(yè)几颜,尤其是有外包性質(zhì)倍试,門(mén)檻極低,低到令人發(fā)指蛋哭,我在公司下面帶了三個(gè)那種培訓(xùn)機(jī)構(gòu)出來(lái)的易猫,都是學(xué)了幾個(gè)月轉(zhuǎn)身包裝簡(jiǎn)歷就出來(lái)面試了,那的工資低還比你能加班具壮!

后來(lái)實(shí)在不想每天這樣疲于拼命的機(jī)械式生活拾并,想著多花時(shí)間去學(xué)習(xí)梦抢,然后跳槽去好一點(diǎn)的公司险耀!然而現(xiàn)實(shí)告訴你旷痕,我最缺的就是時(shí)間拿霉!直到拉勾推出的大數(shù)據(jù)高薪訓(xùn)練營(yíng)蹬竖。關(guān)于技術(shù)類(lèi)的學(xué)習(xí)色瘩,我有點(diǎn)排斥找培訓(xùn)機(jī)構(gòu)锥腻,覺(jué)得自己可以通過(guò)自學(xué)吠勘,在網(wǎng)上翻閱資料啊性芬,找視頻之類(lèi)的方式學(xué),因?yàn)橄嘈抛约旱膶W(xué)習(xí)能力剧防。但是大家也都知道植锉,網(wǎng)上找的這些東西都能學(xué)會(huì),也可以看得懂峭拘。但是當(dāng)自己學(xué)多了就感覺(jué)自己學(xué)的很雜俊庇,一點(diǎn)都沒(méi)有系統(tǒng)性的學(xué)。而且相對(duì)于網(wǎng)上找的免費(fèi)的視頻鸡挠,內(nèi)容很沒(méi)有深度辉饱,TB上買(mǎi)的視頻有些章節(jié)的確實(shí)還行,但是感覺(jué)是那種很久之前的東西拿出來(lái)不停的賣(mài)拣展,而且關(guān)于技術(shù)方面的東西彭沼,肯定是會(huì)有不明白的地方,當(dāng)然遇到這些肯定第一時(shí)間是自己去網(wǎng)絡(luò)上找找解決方案备埃,或者去了解為什么姓惑。但是很多東西確實(shí)在網(wǎng)絡(luò)上找不到褐奴,久而久之,就積累了各種問(wèn)題挺益。

之前也看過(guò)很多培訓(xùn)機(jī)構(gòu)歉糜,像什么八斗學(xué)院,馬士兵教育望众,金訊教育等等匪补,經(jīng)常發(fā)一些二學(xué)員就業(yè)的截圖,薪資都特別高烂翰,但其實(shí)在這一行的都知道夯缺,大數(shù)據(jù)這塊薪資雖然高,但也沒(méi)有高特別多甘耿,只是門(mén)檻高踊兜,說(shuō)實(shí)話,很討厭這種虛假營(yíng)銷(xiāo)佳恬。

選擇拉勾的原因

1. 朋友推薦

剛開(kāi)始知道拉勾除了Java高薪訓(xùn)練營(yíng)捏境,但是并不是很感興趣,后來(lái)朋友報(bào)名了Java高薪訓(xùn)練營(yíng)毁葱,反饋很好垫言,恰逢拉勾推出了大數(shù)據(jù)高薪訓(xùn)練營(yíng),就想著說(shuō)同一家公司的課程倾剿,質(zhì)量應(yīng)該差不多筷频,就抱著試一試的想法找拉勾的老師聊了聊,聽(tīng)完介紹感覺(jué)還可以前痘,就報(bào)名了凛捏。

2. 拉勾本身

拉勾本身就是做招聘的,對(duì)企業(yè)需求這一塊更加了解企業(yè)需要什么樣能力的人芹缔,那么他們的課程在這塊針對(duì)性肯定比其他機(jī)構(gòu)好

結(jié)果

1. 個(gè)人收獲

算算從開(kāi)班到現(xiàn)在坯癣,已經(jīng)五個(gè)月了,課程已經(jīng)學(xué)了一半乖菱,不是我學(xué)的很慢坡锡,而是課程質(zhì)量真的很高,每一個(gè)模塊單獨(dú)拿出來(lái)都可以是一門(mén)課了窒所,特別是一塊內(nèi)容學(xué)完就有一個(gè)實(shí)際項(xiàng)目等著你去做鹉勒,而不是demo!現(xiàn)在養(yǎng)成了學(xué)習(xí)的習(xí)慣之后完全停不下來(lái)了吵取!在這里禽额,我已經(jīng)經(jīng)歷了完整的離線數(shù)倉(cāng)開(kāi)發(fā),包括服務(wù)器選型,技術(shù)選型等等脯倒,在需求這塊实辑,老師帶著我們一個(gè)一個(gè)需求的講解,對(duì)于復(fù)雜的需求和實(shí)現(xiàn)藻丢,老師會(huì)先給出一個(gè)與之相關(guān)但是比較基礎(chǔ)的需求或者實(shí)現(xiàn)剪撬,讓我們一步一步的學(xué)習(xí)。相比學(xué)之前的我悠反,現(xiàn)在的我可以有底氣的說(shuō)具體某個(gè)組件怎么用残黑,為什么這么用,同類(lèi)產(chǎn)品有哪些斋否,為什么選擇這個(gè)而不是其他的梨水,甚至部分原理源碼都可以說(shuō)出來(lái),每一個(gè)模塊的最后老師都會(huì)帶著我們深入底層原理去了解具體某一個(gè)功能的實(shí)現(xiàn)茵臭,也會(huì)帶著我們?nèi)テ饰鲈创a疫诽,看看源碼是怎樣寫(xiě)的!

2. 課程內(nèi)容

課程說(shuō)的再多也不如自己去看旦委,我給幾張知識(shí)思維導(dǎo)圖奇徒,看過(guò)就知道干貨有多少了!

Apache Hadoop
Apache Hive.png

教學(xué)服務(wù)

  1. 班主任每天催學(xué)習(xí)缨硝,提醒交作業(yè)逼龟,安排直播課,帶動(dòng)群里學(xué)習(xí)氣氛追葡,服務(wù)很周到
  2. 導(dǎo)師解答超級(jí)耐心,不會(huì)因?yàn)槟銌?wèn)的問(wèn)題有多簡(jiǎn)單或者稍微百度以下就能明白奕短,還會(huì)根據(jù)你問(wèn)的問(wèn)題宜肉,舉一反三,給你講一些相關(guān)的知識(shí)
  3. 關(guān)于作業(yè)翎碑,每一個(gè)知識(shí)點(diǎn)結(jié)束谬返,都會(huì)有小作業(yè),每一個(gè)模塊結(jié)束都會(huì)有一個(gè)大作業(yè)日杈,每一份作業(yè)導(dǎo)師都會(huì)批改遣铝,只有批改通過(guò)了才能學(xué)習(xí)接下來(lái)的內(nèi)容

內(nèi)推服務(wù)

群里已經(jīng)有好幾波內(nèi)推了,這個(gè)月還和京東合作莉擒,成立專屬內(nèi)推酿炸,解決就業(yè)問(wèn)題。而且投簡(jiǎn)歷之前涨冀,可以去找導(dǎo)師修改簡(jiǎn)歷填硕,讓你的簡(jiǎn)歷過(guò)關(guān)的機(jī)會(huì)更高,也會(huì)對(duì)你進(jìn)行面試前的指導(dǎo),簡(jiǎn)直貼心的不要不要扁眯!

個(gè)人的兩句話

  1. 自學(xué)固然可以壮莹,但是時(shí)間成本很高,而且知識(shí)并不系統(tǒng)姻檀,是時(shí)間成本更高還是培訓(xùn)費(fèi)成本更高命满,還有你一個(gè)人能否堅(jiān)持學(xué)習(xí),不受外界誘惑绣版?

  2. 對(duì)于拉勾胶台,我簡(jiǎn)而言之,豐富而完善的知識(shí)體系僵娃,行業(yè)大咖的直播解答概作,獨(dú)家的內(nèi)推資源,導(dǎo)師班主任全程伴讀默怨,在你偷懶的時(shí)候甩出小鞭子讯榕,定期測(cè)評(píng),完善的作業(yè)機(jī)制匙睹,良好的學(xué)習(xí)環(huán)境


下面正文開(kāi)始


一愚屁、HDFS概述

1. HDFS產(chǎn)出背景及定義

  1. HDFS產(chǎn)生背景

隨著數(shù)據(jù)量越來(lái)越大,在一個(gè)操作系統(tǒng)存不下所有的數(shù)據(jù)痕檬,那么就分配到更多的操作系統(tǒng)管理的磁盤(pán)中霎槐,但是不方便管理和維護(hù),迫切需要一種系統(tǒng)來(lái)管理多臺(tái)機(jī)器上的文件梦谜,這就是分布式文件管理系統(tǒng)丘跌。HDFS只是分布式文件管理系統(tǒng)中的一種。

  1. HDFS定義

    HDFS(Hadoop Distributed File System)唁桩,它是一個(gè)文件系統(tǒng)闭树,用于存儲(chǔ)文件,通過(guò)目錄樹(shù)來(lái)定位文件荒澡;其次报辱,它是分布式的,由很多服務(wù)器聯(lián)合起來(lái)實(shí)現(xiàn)其功能单山,集群中的服務(wù)器有各自的角色碍现,HDFS是分布式存儲(chǔ)服務(wù)。

    HDFS的使用場(chǎng)景:適合一次寫(xiě)入米奸,多次讀出的場(chǎng)景昼接,且不支持文件的修改。適合用來(lái)做數(shù)據(jù)分析悴晰,并不適合用來(lái)做網(wǎng)盤(pán)應(yīng)用辩棒。

2. HDFS優(yōu)缺點(diǎn)

  1. 優(yōu)點(diǎn):

    • 高容錯(cuò)性

      • 數(shù)據(jù)自動(dòng)保存多個(gè)副本。它通過(guò)增加副本的形式,提高容錯(cuò)性一睁。

      • 某一個(gè)副本丟失以后钻弄,它可以自動(dòng)恢復(fù)。

    • 適合處理大數(shù)據(jù)

      • 數(shù)據(jù)規(guī)模:能夠處理數(shù)據(jù)規(guī)模達(dá)到GB者吁、TB窘俺、甚至PB級(jí)別的數(shù)據(jù);
      • 文件規(guī)模:能夠處理百萬(wàn)規(guī)模以上的文件數(shù)量复凳,數(shù)量相當(dāng)之大瘤泪。
    • 可構(gòu)建在廉價(jià)機(jī)器上,通過(guò)多副本機(jī)制育八,提高可靠性对途。

      ?

  2. 缺點(diǎn):

    • 不適合低延時(shí)數(shù)據(jù)訪問(wèn),比如毫秒級(jí)的存儲(chǔ)數(shù)據(jù)髓棋,是做不到的实檀。

    • 無(wú)法高效的對(duì)大量小文件進(jìn)行存儲(chǔ)。

      • 存儲(chǔ)大量小文件的話按声,它會(huì)占用NameNode大量的內(nèi)存來(lái)存儲(chǔ)文件目錄和塊信息膳犹。這樣是不可取的,因?yàn)镹ameNode的內(nèi)存總是有限的签则;
      • 小文件存儲(chǔ)的尋址時(shí)間會(huì)超過(guò)讀取時(shí)間须床,它違反了HDFS的設(shè)計(jì)目標(biāo)。
    • 不支持并發(fā)寫(xiě)入渐裂、文件隨機(jī)修改豺旬。

      • 一個(gè)文件只能有一個(gè)寫(xiě),不允許多個(gè)線程同時(shí)寫(xiě)柒凉;

      • 僅支持?jǐn)?shù)據(jù)append(追加)哈垢,不支持文件的隨機(jī)修改。

3. HDFS的重要概念

HDFS 通過(guò)統(tǒng)一的命名空間目錄樹(shù)來(lái)定位文件扛拨; 另外,它是分布式的举塔,由很多服務(wù)器?聯(lián)合起來(lái)實(shí)現(xiàn)其功能绑警,集群中的服務(wù)器?有各自的角色(分布式本質(zhì)是拆分,各司其職)

  1. 典型的 Master/Slave 架構(gòu)

    • HDFS 的架構(gòu)是典型的 Master/Slave 結(jié)構(gòu)
    • HDFS 集群往往是一個(gè) NameNode+多個(gè)DataNode 組成(HA架構(gòu)會(huì)有兩個(gè)NameNode央渣,聯(lián)邦機(jī)制
    • NameNode 是集群的主節(jié)點(diǎn)计盒,DataNode 是集群的從節(jié)點(diǎn)
  2. 分塊存儲(chǔ)(block機(jī)制)

    • HDFS 中的文件在物理上是 分塊存儲(chǔ)(block)的,塊的大小可以通過(guò)配置參數(shù)來(lái)規(guī)定
    • Hadoop2.x 版本中默認(rèn)的block大小是 128M芽丹,老版本默認(rèn)是64M
    • 切分規(guī)則:如果有兩個(gè)文件北启,分別是 200M 和 20M,那么第一個(gè)文件先分成兩個(gè)切片(128M + 72M),第二個(gè)文件分成一個(gè)切片(20M)咕村,共三個(gè)切片
  3. 命名空間(NameSpace)

    • HDFS

      支持傳統(tǒng)的層次型文件組織結(jié)構(gòu)场钉,用戶或者應(yīng)用程序可以創(chuàng)建目錄,然后將文件保存在這些目錄里懈涛。文件系統(tǒng)名字空間的層次結(jié)構(gòu)和大多數(shù)現(xiàn)有的文件系統(tǒng)類(lèi)似:用戶可以創(chuàng)建逛万、刪除、移動(dòng)或重命名文件

    • Namenode

      負(fù)責(zé)維護(hù)文件系統(tǒng)的名字空間批钠,任何對(duì)文件系統(tǒng)名字空間或?qū)傩缘男薷亩紝⒈?Namenode 記錄下來(lái)

    • 抽象目錄樹(shù)

      HDFS 提供給客戶單一的一個(gè)抽象目錄樹(shù)宇植,用戶不知道這些文件是存儲(chǔ)在哪個(gè)dataNode上

      訪問(wèn)形式:hdfs://namenode的hostname:port/test/input

      例如:hdfs://linux121:9000/test/input

  4. NameNode 元數(shù)據(jù)管理

    • 我們把 目錄結(jié)構(gòu)文件分塊位置信息 叫做元數(shù)據(jù)
    • NameNode 的元數(shù)據(jù)記錄每一個(gè)文件所對(duì)應(yīng)的 block 信息(block的 id 以及所在的 DataNode 節(jié)點(diǎn)的信息)
  5. DataNode 數(shù)據(jù)存儲(chǔ)

    • 文件的各個(gè) block 的具體存儲(chǔ)管理由 DataNode 節(jié)點(diǎn)承擔(dān)
    • 一個(gè) block 會(huì)有多個(gè) DataNode 來(lái)存儲(chǔ),DataNode 會(huì)定時(shí)向 NameNode 來(lái)匯報(bào)自己持有的 block 信息(<font color=red>這就是高容錯(cuò)的體現(xiàn)埋心,很重要</font>
  6. 副本機(jī)制

    • 為了容錯(cuò)指郁,文件的所有 block 都會(huì)有副本,默認(rèn)是 3 個(gè)(包括本來(lái)的block拷呆,一共 3 個(gè))闲坎。每個(gè)文件的 block大小副本系數(shù) 都是可配置

    • 應(yīng)用程序可以指定某個(gè)文件的副本數(shù)目,副本系數(shù)可以在文件創(chuàng)建的時(shí)候指定洋腮,也可以在之后改變

    • 如果副本數(shù)量設(shè)置為 10箫柳,但設(shè)備數(shù)只有 3臺(tái),那么不會(huì)真正創(chuàng)建 10 個(gè)副本啥供,而是創(chuàng)建相當(dāng)于設(shè)備數(shù)量的副本悯恍,即 3個(gè)副本。等設(shè)備數(shù)增加到 10 臺(tái)伙狐,創(chuàng)建的副本數(shù)才達(dá)到 10 臺(tái)(<font color=red>很重要</font>)

  7. 一次寫(xiě)入涮毫,多次讀出

    • HDFS 是設(shè)計(jì)成適應(yīng) 一次寫(xiě)入,多次讀出 的場(chǎng)景贷屎,且不支持文件的隨機(jī)修改(支持追加寫(xiě)入罢防,不支持隨機(jī)更新)
    • 因此,HDFS 適合用來(lái)做 大數(shù)據(jù)分析的底層存儲(chǔ)服務(wù)唉侄,并不適合用來(lái)做網(wǎng)盤(pán)等應(yīng)用(修改不方便咒吐,延遲大,網(wǎng)絡(luò)開(kāi)銷(xiāo)大属划,成本太高)

4. HDFS架構(gòu)

  1. NameNode: HDFS集群的管理者恬叹,Master
  • 維護(hù)管理Hdfs的名稱空間(NameSpace)
  • 維護(hù)副本策略
  • 記錄?件塊(Block)的映射信息
  • 負(fù)責(zé)處理客戶端讀寫(xiě)請(qǐng)求
  1. DataNode: NameNode下達(dá)命令,DataNode執(zhí)行實(shí)際操作同眯,Slave節(jié)點(diǎn)绽昼。

    • 保存實(shí)際的數(shù)據(jù)塊

    • 負(fù)責(zé)數(shù)據(jù)塊的讀寫(xiě)

  1. Client: 客戶端
    • 上傳?文件到HDFS的時(shí)候,Client負(fù)責(zé)將?件切分成Block,然后進(jìn)行上傳
    • 請(qǐng)求NameNode交互须蜗,獲取文件的位置信息
    • 讀取或?qū)?文件硅确,與DataNode交互
    • Client可以使?一些命令來(lái)管理HDFS或者訪問(wèn)HDFS

二目溉、 HDFS 客戶端操作

1. Shell命令行操作HDFS

  1. 基本語(yǔ)法

    • bin/hadoop fs 具體命令
    • bin/hdfs dfs 具體命令(<font color=red>推薦</font>)
  2. 命令?全

    [root@linux121 hadoop-2.9.2]# bin/hdfs dfs
    Usage: hadoop fs [generic options]
            [-appendToFile <localsrc> ... <dst>]
            [-cat [-ignoreCrc] <src> ...]
            [-checksum <src> ...]
            [-chgrp [-R] GROUP PATH...]
            [-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
             
    [-chown [-R] [OWNER][:[GROUP]] PATH...]
            [-copyFromLocal [-f] [-p] [-l] [-d] <localsrc> ... <dst>]
            [-copyToLocal [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
            [-count [-q] [-h] [-v] [-t [<storage type>]] [-u] [-x] <path> ...]
            [-cp [-f] [-p | -p[topax]] [-d] <src> ... <dst>]
            [-createSnapshot <snapshotDir> [<snapshotName>]]
            [-deleteSnapshot <snapshotDir> <snapshotName>]
            [-df [-h] [<path> ...]]
            [-du [-s] [-h] [-x] <path> ...]
            [-expunge]
            [-find <path> ... <expression> ...]
            [-get [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
            [-getfacl [-R] <path>]
            [-getfattr [-R] {-n name | -d} [-e en] <path>]
            [-getmerge [-nl] [-skip-empty-file] <src> <localdst>]
            [-help [cmd ...]]
            [-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [<path> ...]]
            [-mkdir [-p] <path> ...]
            [-moveFromLocal <localsrc> ... <dst>]
            [-moveToLocal <src> <localdst>]
            [-mv <src> ... <dst>]
            [-put [-f] [-p] [-l] [-d] <localsrc> ... <dst>]
            [-renameSnapshot <snapshotDir> <oldName> <newName>]
            [-rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ...]
            [-rmdir [--ignore-fail-on-non-empty] <dir> ...]
            [-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec>
    <path>]]
            [-setfattr {-n name [-v value] | -x name} <path>]
            [-setrep [-R] [-w] <rep> <path> ...]
            [-stat [format] <path> ...]
            [-tail [-f] <file>]
            [-test -[defsz] <path>]
            [-text [-ignoreCrc] <src> ...]
            [-touchz <path> ...]
            [-truncate [-w] <length> <path> ...]
            [-usage [cmd ...]]
            
    Generic options supported are:
    -conf <configuration file>        specify an application configuration file
    -D <property=value>               define a value for a given property
    -fs <file:///|hdfs://namenode:port> specify default filesystem URL to use, overrides 'fs.defaultFS' property from configurations.
    -jt <local|resourcemanager:port>  specify a ResourceManager
    -files <file1,...>                specify a comma-separated list of files to be copied to the map reduce cluster
    -libjars <jar1,...>               specify a comma-separated list of jar files to be included in the classpath
    -archives <archive1,...>          specify a comma-separated list of archives to be unarchived on the compute machines
    
  1. HDFS命令演示

    • 首先啟動(dòng)Hadoop集群(HDFS和YARN要做各自的節(jié)點(diǎn)上啟動(dòng)

      [root@linux121 hadoop-2.9.2]$ sbin/start-dfs.sh
      [root@linux122 hadoop-2.9.2]$ sbin/start-yarn.sh
      
    • -help:輸出這個(gè)命令參數(shù)

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -help rm
      
    • -ls: 顯示?錄信息

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -ls /
      
    • -mkdir: 在HDFS上創(chuàng)建目錄

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -mkdir -p /lagou/bigdata
      
    • -moveFromLocal: 從本地剪切粘貼到HDFS

      [root@linux121 hadoop-2.9.2]$ touch hadoop.txt
      [root@linux121 hadoop-2.9.2]$ hdfs dfs  -moveFromLocal  ./hadoop.txt /lagou/bigdata
      
    • -appendToFile: 追加?個(gè)文件到已經(jīng)存在的?件末尾

      [root@linux121 hadoop-2.9.2]$ touch hdfs.txt
      [root@linux121 hadoop-2.9.2]$ vi hdfs.txt
      
      輸入
      namenode datanode block replication
      [root@linux121 hadoop-2.9.2]$ hdfs dfs -appendToFile hdfs.txt /lagou/bigdata/hadoop.txt
      
    • -cat: 顯示文件內(nèi)容

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -cat /lagou/bigdata/hadoop.txt
      
    • -chgrp 、-chmod菱农、-chown: Linux?件系統(tǒng)中的?法一樣缭付,修改文件所屬權(quán)限

       [root@linux121 hadoop-2.9.2]$ hdfs dfs  -chmod  666 /lagou/bigdata/hadoop.txt
      [root@linux121 hadoop-2.9.2]$ hdfs dfs  -chown  root:root /lagou/bigdata/hadoop.txt
      
    • -copyFromLocal: 從本地?件系統(tǒng)中拷?文件到HDFS路徑去

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -copyFromLocal README.txt /
      
    • -copyToLocal: 從HDFS拷貝到本地

       [root@linux121 hadoop-2.9.2]$ hdfs dfs -copyToLocal /lagou/bigdata/hadoop.txt ./
      
    • -cp : 從HDFS的?個(gè)路徑拷?到HDFS的另一個(gè)路徑

       [root@linux121 hadoop-2.9.2]$ hdfs dfs -cp /lagou/bigdata/hadoop.txt /hdfs.txt
      
    • -mv: 在HDFS?錄中移動(dòng)文件

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -mv /hdfs.txt /lagou/bigdata/
      
    • -get: 等同于copyToLocal,就是從HDFS下載文件到本地

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -get /lagou/bigdata/hadoop.txt ./
      
    • -put: 等同于copyFromLocal

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -mkdir -p /user/root/test/ 
      
      #本地?文件系統(tǒng)創(chuàng)建yarn.txt
      [root@linux121 hadoop-2.9.2]$ vim yarn.txt
      resourcemanager nodemanager
      [root@linux121 hadoop-2.9.2]$ hdfs dfs -put ./yarn.txt /user/root/test/
      
    • -tail: 顯示?個(gè)?件的末尾

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -tail /user/root/test/yarn.txt
      
    • -rm: 刪除?件或?件夾

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -rm /user/root/test/yarn.txt
      
    • -rmdir: 刪除空?錄

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -mkdir /test
      [root@linux121 hadoop-2.9.2]$ hdfs dfs -rmdir /test
      
    • -du: 統(tǒng)計(jì)?件夾的?小信息

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -du -s -h /user/root/test
      [root@linux121 hadoop-2.9.2]$ hdfs dfs -du  -h /user/root/test
      
    • -setrep: 設(shè)置HDFS中?件的副本數(shù)量

      [root@linux121 hadoop-2.9.2]$ hdfs dfs -setrep 10 /lagou/bigdata/hadoop.txt
      

2. JAVA客戶端

2.1 客戶端環(huán)境準(zhǔn)備

  1. 將Hadoop-2.9.2安裝包解壓到非中?路徑(例如:E:\hadoop-2.9.2)大莫。
  1. 配置HADOOP_HOME環(huán)境變量
    image-20201130152417302.png
  1. 配置Path環(huán)境變量蛉腌。
  1. 創(chuàng)建?個(gè)Maven工程ClientDemo

  2. 導(dǎo)入相應(yīng)的依賴坐標(biāo)+日志配置文件

    • 需要導(dǎo)入三個(gè)模塊:hadoop-common、hadoopclient只厘、hadoop-hdfs

      <dependencies>
        
        <!-- 導(dǎo)入三個(gè)模塊:hadoop-common烙丛、hadoopclient、hadoop-hdfs -->
        
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
         <dependency>
             <groupId>org.apache.hadoop</groupId>
             <artifactId>hadoop-common</artifactId>
             <version>2.9.2</version>
         </dependency>
        
         <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoopclient -->
         <dependency>
             <groupId>org.apache.hadoop</groupId>
             <artifactId>hadoop-client</artifactId>
             <version>2.9.2</version>
         </dependency>
        
         <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs -->
         <dependency>
             <groupId>org.apache.hadoop</groupId>
             <artifactId>hadoop-hdfs</artifactId>
             <version>2.9.2</version>
         </dependency>
        
        <!-- 單元測(cè)試 -->
        <dependency>
             <groupId>junit</groupId>
         <artifactId>junit</artifactId>
             <version>RELEASE</version>
         </dependency>
        
        <!-- 日志打印 -->
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-core</artifactId>
             <version>2.8.2</version>
         </dependency>
      
      </dependencies>
      
    • 為了便于控制程序運(yùn)行打印的日志數(shù)量羔味,需要在項(xiàng)目的 src/main/resources 目錄下河咽,新建一個(gè)文件,命名為 log4j.properties赋元,文件內(nèi)容如下:

      log4j.rootLogger=INFO, stdout
      log4j.appender.stdout=org.apache.log4j.ConsoleAppender
      log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
      log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
      log4j.appender.logfile=org.apache.log4j.FileAppender
      log4j.appender.logfile.File=target/spring.log
      log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
      log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
      
  3. 創(chuàng)建包名:com.lagou.hdfs

  4. 創(chuàng)建HdfsClient類(lèi)

     public class HdfsClient{
        @Test
        public void testMkdirs() throws IOException, InterruptedException, URISyntaxException {
            // 1 獲取?件系統(tǒng)
            Configuration configuration = new Configuration();
            // 配置在集群上運(yùn)行
            // configuration.set("fs.defaultFS", "hdfs://linux121:9000");
            // FileSystem fs = FileSystem.get(configuration);
            FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"),
            configuration, "root");
            // 2 創(chuàng)建目錄
            fs.mkdirs(new Path("/test"));
            // 3 關(guān)閉資源
            fs.close();
     }
    }
    

會(huì)遇到的問(wèn)題:

  1. 如果不指定操作 HDFS 集群的用戶信息忘蟹,默認(rèn)是 獲取當(dāng)前操作系統(tǒng)的用戶信息,出現(xiàn)權(quán)限被拒絕的問(wèn)題搁凸,報(bào)錯(cuò)如下:

出現(xiàn)問(wèn)題的原因:

由于 HDFS 的權(quán)限管理機(jī)制是:用戶告訴 hdfs 自己是什么用戶媚值,hdfs 都會(huì)相信,認(rèn)為用戶不會(huì)做壞事护糖。HDFS?件權(quán)限的目的褥芒,防?好?做錯(cuò)事,?不是阻?壞人做壞事嫡良。HDFS相信你告訴我你是誰(shuí)锰扶,你就是誰(shuí)。因此這種權(quán)限管理比較雞肋

解決辦法:

  1. 把 根目錄 的權(quán)限設(shè)置為 777 寝受,關(guān)于文件權(quán)限管理 交給其他軟件去做

    hdfs dfs -R 777 /
    
  2. 在配置文件 hdfs-site.xml 中添加以下屬性坷牛,以關(guān)閉 HDFS 集群權(quán)限校驗(yàn),修改完成之后要分發(fā)到其它節(jié)點(diǎn)很澄,同時(shí)要重啟HDFS集群

    vim hdfs-site.xml
    
    #添加如下屬性
    <property>
         <name>dfs.permissions.enabled</name>
         <value>false</value>
    </property>
    
  3. 指定用戶信息獲取 FileSystem 對(duì)象

    FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root")
    
  1. windows 解壓安裝 Hadoop后京闰,在調(diào)用相關(guān)API操作 HDFS 集群時(shí)可能會(huì)報(bào)錯(cuò),如下圖:
    image-20201130153945039.png

出現(xiàn)問(wèn)題的原因:

這是由于 Hadoop 安裝缺少 windows 操作系統(tǒng)相關(guān)文件所致

解決辦法:

將 winutils.exe 拷貝到 windows 系統(tǒng) Hadoop 安裝目錄的 bin 目錄下即可

  1. IDEA 啟動(dòng) Hadoop 的任務(wù)時(shí)甩苛,出現(xiàn)如下報(bào)錯(cuò):

解決辦法:

將 Hadoop.dll 文件 添加到 C:\Windows\System32 中

參數(shù)的優(yōu)先級(jí)

當(dāng)在配置文件蹂楣,java 代碼中,包括hdfs服務(wù)器的默認(rèn)配置浪藻,都設(shè)置副本數(shù)量時(shí),參數(shù)的優(yōu)先級(jí)是:

<font color=red>代碼中設(shè)置的值 -->用戶自定義配置文件 -->服務(wù)?的默認(rèn)配置</font>

2.2 HDFS的API操作

  1. 上傳文件

    • 可通過(guò) configuration.set("dfs.replication", "2") 設(shè)置副本數(shù)量

      @Test
      public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {
      
          // 1 獲取?文件系統(tǒng)
         Configuration configuration = new Configuration();
         configuration.set("dfs.replication", "2");
         FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root");
      
          // 2上傳?文件
         fs.copyFromLocalFile(new Path("e:/lagou.txt"), new Path("/lagou.txt"));
      
          // 3 關(guān)閉資源
         fs.close();
      }
      
    • 也可通過(guò) 配置文件 hdfs-site.xml 來(lái)指定乾翔,文件放在 resources 目錄下

      <font color=red>注:配置文件名 不能寫(xiě)錯(cuò)0施戴!</font>

      <?xml version="1.0" encoding="UTF-8"?>
      <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
      
      <configuration>
          <property>
              <name>dfs.replication</name>
              <value>1</value>
          </property>
      </configuration>
      
  2. 下載文件

    @Test
    public void testCopyToLocalFile() throws IOException, InterruptedException, URISyntaxException{
    
        // 1 獲取?文件系統(tǒng)
     Configuration configuration = new Configuration();
     FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root");
    
        // 2 執(zhí)?行行下載操作
     // boolean delSrc 指是否將原?文件刪除
     // Path src 指要下載的?文件路路徑
     // Path dst 指將?文件下載到的路路徑
     // boolean useRawLocalFileSystem 是否開(kāi)啟?文件校驗(yàn)
     fs.copyToLocalFile(false, new Path("/lagou.txt"), newPath("e:/lagou_copy.txt"), true);
        
        // 3 關(guān)閉資源
     fs.close();
    }
    
  3. 刪除文件/文件夾

    @Test
    public void testDelete() throws IOException, InterruptedException, URISyntaxException{
    
        // 1 獲取?文件系統(tǒng)
     Configuration configuration = new Configuration();
     FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root");
    
        // 2 執(zhí)?行行刪除
     fs.delete(new Path("/api_test/"), true);
    
        // 3 關(guān)閉資源
     fs.close();
    }
    
  4. HDFS文件名更改

    @Test
    public void testRename() throws IOException, InterruptedException, URISyntaxException{
    
     // 1 獲取文件系統(tǒng)
     Configuration configuration = new Configuration();
     FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root");
         
     // 2 修改文件名稱
     fs.rename(new Path("/banzhang.txt"), new Path("/banhua.txt"));
         
     // 3 關(guān)閉資源
     fs.close();
    }
    
    
  5. 查看 文件名稱、權(quán)限萌丈、長(zhǎng)度赞哗、塊信息

    @Test
    public void testListFiles() throws IOException, InterruptedException, URISyntaxException{
    
        // 1獲取?文件系統(tǒng)
     Configuration configuration = new Configuration();
     FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root");
    
        // 2 獲取?文件詳情
     RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
     
        while(listFiles.hasNext()){
         LocatedFileStatus status = listFiles.next();
         // 輸出詳情
    
            // ?文件名稱
         System.out.println(status.getPath().getName());
    
            // ?長(zhǎng)度
         System.out.println(status.getLen());
        
            // 權(quán)限
         System.out.println(status.getPermission());
    
            // 分組
         System.out.println(status.getGroup());
    
            // 獲取存儲(chǔ)的塊信息
         BlockLocation[] blockLocations = status.getBlockLocations();
         for (BlockLocation blockLocation : blockLocations) {
         
                // 獲取塊存儲(chǔ)的主機(jī)節(jié)點(diǎn)
             String[] hosts = blockLocation.getHosts();
             for (String host : hosts) {
                 System.out.println(host);
             }
         }
    
            System.out.println("-----------華麗的分割線----------");
     }
    
        // 3 關(guān)閉資源
     fs.close();
    } 
    
  6. 區(qū)分文件和文件夾

    @Test
    public void testListStatus() throws IOException, InterruptedException, URISyntaxException{
    
        // 1 獲取?文件配置信息
     Configuration configuration = new Configuration();
     FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root");
    
        // 2 判斷是?文件還是?文件夾
     FileStatus[] listStatus = fs.listStatus(new Path("/"));
     for (FileStatus fileStatus : listStatus) {
         // 如果是?文件
         if (fileStatus.isFile()){ 
                System.out.println("f:"+fileStatus.getPath().getName());
            } else{ 
                System.out.println("d:"+fileStatus.getPath().getName());         
            }
     }
    
         // 3 關(guān)閉資源
     fs.close();
    }
    
  7. 文件上傳 create

    將本地文件上傳到 hdfs 上

    @Test
    public void putFileToHDFS() throws IOException, InterruptedException, URISyntaxException {
    
        // 1 獲取文件系統(tǒng)
     Configuration configuration = new Configuration();
     FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root");
    
        // 2 創(chuàng)建輸?流
     FileInputStream fis = new FileInputStream(new File("e:/lagou.txt"));
    
        // 3 獲取輸出流
     FSDataOutputStream fos = fs.create(new Path("/lagou_io.txt"));
    
        // 4 流的拷貝
     IOUtils.copyBytes(fis, fos, configuration);
    
        // 5 關(guān)閉資源(這里其實(shí)不需要關(guān)閉)
     IOUtils.closeStream(fos);
     IOUtils.closeStream(fis);
     fs.close();
    }
    
  8. 文件下載 open

    將 hdfs 文件下載到本地

    @Test
    public void getFileFromHDFS() throws IOException, InterruptedException, URISyntaxException{
    
        // 1 獲取?文件系統(tǒng)
        Configuration configuration = new Configuration();
     FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root");
    
        // 2 獲取輸?入流
     FSDataInputStream fis = fs.open(new Path("/lagou_io.txt"));
    
        // 3 獲取輸出流
     FileOutputStream fos = new FileOutputStream(new File("e:/lagou_io_copy.txt"));
    
        // 4 流的對(duì)拷
     IOUtils.copyBytes(fis, fos, configuration);
    
        // 5 關(guān)閉資源
     IOUtils.closeStream(fos);
     IOUtils.closeStream(fis);
     fs.close();
    }
    
  9. 定位讀取 seek

    將 HDFS上 的 lagou.txt 的內(nèi)容在控制臺(tái)輸出兩次

    @Test
    public void readFileSeek2() throws IOException, InterruptedException, URISyntaxException{
    
        // 1 獲取?文件系統(tǒng)
     Configuration configuration = new Configuration();
     FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root");
     
        // 2 打開(kāi)輸?入流,讀取數(shù)據(jù)輸出到控制臺(tái)
     FSDataInputStream in = null;
     try{
         in = fs.open(new Path("/lagou.txt"));
         IOUtils.copyBytes(in, System.out, 4096, false);
         
            //從頭再次讀取,偏移量為0 表示從頭讀起
            in.seek(0); 
         IOUtils.copyBytes(in, System.out, 4096, false);
     }finally {
         IOUtils.closeStream(in);
            fs.close();
     }
    }
    

三辆雾、 HDFS讀寫(xiě)解析

1. HDFS讀數(shù)據(jù)流程

HDFS讀數(shù)據(jù)流程:

  1. 客戶端通過(guò)Distributed FileSystemNameNode請(qǐng)求下載文件肪笋,NameNode通過(guò)查詢?cè)獢?shù)據(jù),找到文件塊所在的DataNode地址度迂。
  2. 挑選一臺(tái)DataNode(就近原則藤乙,然后隨機(jī))服務(wù)器,請(qǐng)求讀取數(shù)據(jù)惭墓。
  3. DataNode開(kāi)始傳輸數(shù)據(jù)給客戶端(從磁盤(pán)里面讀取數(shù)據(jù)輸入流坛梁,以Packet(64KB)為單位來(lái)做校驗(yàn))。
  4. 客戶端以Packet為單位接收腊凶,先在本地緩存划咐,然后寫(xiě)入目標(biāo)文件。

2.HDFS寫(xiě)數(shù)據(jù)流程

HDFS寫(xiě)數(shù)據(jù)流程:

  1. 客戶端通過(guò)Distributed FileSystem模塊向NameNode請(qǐng)求上傳文件钧萍,NameNode檢查目標(biāo)文件是否已存在褐缠,父目錄是否存在。
  2. NameNode返回是否可以上傳风瘦。
  3. 客戶端請(qǐng)求第一個(gè) Block上傳到哪幾個(gè)DataNode服務(wù)器上队魏。
  4. NameNode返回3個(gè)DataNode節(jié)點(diǎn),分別為dn1弛秋、dn2器躏、dn3。
  5. 客戶端通過(guò)FSDataOutputStream模塊請(qǐng)求dn1上傳數(shù)據(jù)蟹略,dn1收到請(qǐng)求會(huì)繼續(xù)調(diào)用dn2登失,然后dn2調(diào)用dn3,將這個(gè)通信管道建立完成挖炬。
  6. dn1揽浙、dn2、dn3逐級(jí)應(yīng)答客戶端意敛。
  7. 客戶端開(kāi)始往dn1上傳第一個(gè)Block(先從磁盤(pán)讀取數(shù)據(jù)放到一個(gè)本地內(nèi)存緩存)馅巷,以Packet(64KB)為單位,dn1收到一個(gè)Packet就會(huì)傳給dn2草姻,dn2傳給dn3钓猬;dn1每傳一個(gè)packet會(huì)放入一個(gè)應(yīng)答隊(duì)列等待應(yīng)答。
  8. 當(dāng)一個(gè)Block傳輸完成之后撩独,客戶端再次請(qǐng)求NameNode上傳第二個(gè)Block的服務(wù)器敞曹。(重復(fù)執(zhí)行3-7步)账月。

驗(yàn)證Packet代碼:

  • @Test
    public void testUploadPacket() throws IOException {
        //1 準(zhǔn)備讀取本地文件的輸入流
        final FileInputStream in = new FileInputStream(new File("e:/lagou.txt"));
        //2 準(zhǔn)備好寫(xiě)出數(shù)據(jù)到hdfs的輸出流
        final FSDataOutputStream out = fs.create(new Path("/lagou.txt"), new Progressable() {
            public void progress() {
                //這個(gè)progress?法就是每傳輸64KB(packet)就會(huì)執(zhí)行一次
                System.out.println("&");
            }
        });
        //3 實(shí)現(xiàn)流拷貝
        IOUtils.copyBytes(in, out, configuration);
        //默認(rèn)關(guān)閉流選項(xiàng)是true,所以會(huì)?動(dòng)關(guān)閉
        //4 關(guān)流 可以再次關(guān)閉也可以不關(guān)了
    }
    

四澳迫、 NameNode和SecondaryNameNode

1. NN和2NN工作機(jī)制

問(wèn)題引出: NameNode如何管理和存儲(chǔ)元數(shù)據(jù)?

計(jì)算機(jī)中存儲(chǔ)數(shù)據(jù)的兩種方式:磁盤(pán)局齿、內(nèi)存

  • 元數(shù)據(jù)存儲(chǔ)磁盤(pán):存儲(chǔ)磁盤(pán)?法?對(duì)客戶端對(duì)元數(shù)據(jù)信息的隨機(jī)訪問(wèn),還有響應(yīng)客戶請(qǐng)求橄登,必然是效率過(guò)低抓歼。但是安全性?
  • 元數(shù)據(jù)存儲(chǔ)內(nèi)存:元數(shù)據(jù)存放內(nèi)存,可以高效的查詢以及快速響應(yīng)客戶端的查詢請(qǐng)求拢锹,數(shù)據(jù)保存在內(nèi)存谣妻,如果斷點(diǎn),內(nèi)存中的數(shù)據(jù)全部丟失面褐。安全性低

解決辦法: 內(nèi)存+磁盤(pán);NameNode內(nèi)存+FsImage的?件(磁盤(pán))

新問(wèn)題: 磁盤(pán)和內(nèi)存中元數(shù)據(jù)如何劃分?

兩個(gè)數(shù)據(jù)一模?樣拌禾,還是兩個(gè)數(shù)據(jù)合并到一起才是?份完整的數(shù)據(jù)呢?

  • 如果兩份數(shù)據(jù)一模一樣的話,客戶端 Client 如果對(duì)元數(shù)據(jù)進(jìn)行增刪改操作展哭,則需要時(shí)刻保證兩份數(shù)據(jù)的一致性湃窍,導(dǎo)致效率變低
  • 如果兩份數(shù)據(jù)合并后 ==> 完整數(shù)據(jù)的情況。NameNode 引入了 edits 文件(日志文件匪傍,只能追加寫(xiě)入)您市,記錄了client 的增刪改操作,而不再讓 NameNode 把數(shù)據(jù) dump 出來(lái)形成 fsimage文件(讓 NameNode 專注于處理客戶端的請(qǐng)求)
  • edits文件:文件生成快役衡,恢復(fù)慢茵休;fsimage文件:文件生成慢,恢復(fù)快

新問(wèn)題: 誰(shuí)來(lái)負(fù)責(zé)文件合并手蝎?

如果長(zhǎng)時(shí)間添加數(shù)據(jù)到Edits中榕莺,會(huì)導(dǎo)致該文件數(shù)據(jù)過(guò)大,效率降低棵介,而且一旦斷電钉鸯,恢復(fù)元數(shù)據(jù)需要的時(shí)間過(guò)長(zhǎng)。因此邮辽,需要定期進(jìn)行FsImage和Edits的合并唠雕,但是誰(shuí)來(lái)合并?

  • NameNode:NameNode本身任務(wù)重吨述,再負(fù)責(zé)合并岩睁,勢(shì)必效率過(guò)低王凑,甚至?xí)绊懕旧淼娜蝿?wù)
  • 因此撒穷,引入一個(gè)新的節(jié)點(diǎn)SecondaryNamenode,專門(mén)用于FsImage和Edits的合并龙致。

流程分析:

  1. 第一階段:NameNode啟動(dòng)
    1. 第一次啟動(dòng)NameNode格式化后邓夕,創(chuàng)建Fsimage和Edits文件刘莹。如果不是第一次啟動(dòng)亿笤,直接加載編輯日志和鏡像文件到內(nèi)存。
    2. 客戶端對(duì)元數(shù)據(jù)進(jìn)行增刪改的請(qǐng)求栋猖。
    3. NameNode記錄操作日志,更新滾動(dòng)日志(所謂滾動(dòng)日志汪榔,即 把前一階段的日志保存成一個(gè)日志文件蒲拉,再新生成一個(gè)文件,新生成文件后綴帶有 inprogress 字樣)痴腌。
    4. NameNode在內(nèi)存中對(duì)數(shù)據(jù)進(jìn)行增刪改雌团。
  2. 第二階段:Secondary NameNode工作
    1. Secondary NameNode詢問(wèn)NameNode是否需要CheckPoint。直接帶回NameNode是否檢查結(jié)果士聪。
    2. Secondary NameNode請(qǐng)求執(zhí)行CheckPoint锦援。
    3. NameNode滾動(dòng)正在寫(xiě)的Edits日志。
    4. 將滾動(dòng)前的編輯日志和鏡像文件拷貝到Secondary NameNode剥悟。
    5. Secondary NameNode加載編輯日志和鏡像文件到內(nèi)存灵寺,并合并。
    6. 生成新的鏡像文件fsimage.chkpoint区岗。
    7. 拷貝fsimage.chkpoint到NameNode略板。
    8. NameNode將fsimage.chkpoint重新命名成fsimage。

<font color=red>NN和2NN工作機(jī)制詳解:</font>

  • Fsimage:NameNode內(nèi)存中元數(shù)據(jù)序列化后形成的文件慈缔。

  • Edits:記錄客戶端更新元數(shù)據(jù)信息的每一步操作(可通過(guò)Edits運(yùn)算出元數(shù)據(jù))叮称。

  • NameNode啟動(dòng)時(shí),先滾動(dòng)Edits并生成一個(gè)空的edits.inprogress藐鹤,然后加載Edits和Fsimage到內(nèi)存中瓤檐,此時(shí)NameNode內(nèi)存就持有最新的元數(shù)據(jù)信息。Client開(kāi)始對(duì)NameNode發(fā)送元數(shù)據(jù)的增刪改的請(qǐng)求娱节,這些請(qǐng)求的操作首先會(huì)被記錄到edits.inprogress中(查詢?cè)獢?shù)據(jù)的操作不會(huì)被記錄在Edits中挠蛉,因?yàn)椴樵儾僮鞑粫?huì)更改元數(shù)據(jù)信息),如果此時(shí)NameNode掛掉括堤,重啟后會(huì)從Edits中讀取元數(shù)據(jù)的信息碌秸。然后,NameNode會(huì)在內(nèi)存中執(zhí)行元數(shù)據(jù)的增刪改的操作悄窃。

  • 由于Edits中記錄的操作會(huì)越來(lái)越多讥电,Edits文件會(huì)越來(lái)越大,導(dǎo)致NameNode在啟動(dòng)加載Edits時(shí)會(huì)很慢轧抗,所以需要對(duì)Edits和Fsimage進(jìn)行合并(所謂合并恩敌,就是將Edits和Fsimage加載到內(nèi)存中,照著Edits中的操作一步步執(zhí)行横媚,最終形成新的Fsimage)纠炮。SecondaryNameNode的作用就是幫助NameNode進(jìn)行Edits和Fsimage的合并工作月趟。

  • SecondaryNameNode首先會(huì)詢問(wèn)NameNode是否需要CheckPoint(觸發(fā)CheckPoint需要滿足兩個(gè)條件中的任意一個(gè),定時(shí)時(shí)間到和Edits中數(shù)據(jù)寫(xiě)滿了)恢口。直接帶回NameNode是否檢查結(jié)果孝宗。SecondaryNameNode執(zhí)行CheckPoint操作,首先會(huì)讓NameNode滾動(dòng)Edits并生成一個(gè)空的edits.inprogress耕肩,滾動(dòng)Edits的目的是給Edits打個(gè)標(biāo)記因妇,以后所有新的操作都寫(xiě)入edits.inprogress,其他未合并的Edits和Fsimage會(huì)拷貝到SecondaryNameNode的本地猿诸,然后將拷貝的Edits和Fsimage加載到內(nèi)存中進(jìn)行合并婚被,生成fsimage.chkpoint,然后將fsimage.chkpoint拷貝給NameNode梳虽,重命名為Fsimage后替換掉原來(lái)的Fsimage址芯。NameNode在啟動(dòng)時(shí)就只需要加載之前未合并的Edits和Fsimage即可,因?yàn)楹喜⑦^(guò)的Edits中的元數(shù)據(jù)信息已經(jīng)被記錄在Fsimage中窜觉。

2. Fsimage和Edits解析

  • NameNode在執(zhí)行格式化之后谷炸,會(huì)在/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name/current?錄下產(chǎn)?如下文件
    • Fsimage?件: 是namenode中關(guān)于元數(shù)據(jù)的鏡像,一般稱為檢查點(diǎn)禀挫,這里包含了HDFS?件系統(tǒng)所有?錄以及?件相關(guān)信息(Block數(shù)量淑廊,副本數(shù)量,權(quán)限等信息)
    • Edits文件 : 存儲(chǔ)了客戶端對(duì)HDFS文件系統(tǒng)所有的更新操作記錄特咆,Client對(duì)HDFS?件系統(tǒng)所有的更新操作都會(huì)被記錄到Edits?件中(不包括查詢操作)
    • seen_txid: 該?件是保存了一個(gè)數(shù)字季惩,數(shù)字對(duì)應(yīng)著最后一個(gè)Edits?件名的數(shù)字
    • VERSION: 該?件記錄namenode的一些版本號(hào)信息,比如:CusterId,namespaceID等
  • NameNode啟動(dòng)時(shí)會(huì)將Fsimage?件加載到內(nèi)存中腻格,同時(shí)也把之前未合并元數(shù)據(jù)的Edits?件加載画拾,集合兩個(gè)文件中的元數(shù)據(jù)這樣保證了NameNode中的元數(shù)據(jù)是最新最全的。通俗點(diǎn)說(shuō)就是NameNode啟動(dòng)時(shí)把Fsimage和Edits?件進(jìn)?了合并菜职。

2.1 Fsimage?件內(nèi)容

  1. 官方地址:https://hadoop.apache.org/docs/r2.9.2/hadoop-project-dist/hadoop-hdfs/HdfsImageViewer.html

  2. 查看oiv和oev命令

    [[root@linux121 current]$ hdfs
    oiv            apply the offline fsimage viewer to an fsimage
    oev            apply the offline edits viewer to an edits file
    
  3. 基本語(yǔ)法

    hdfs oiv -p 文件類(lèi)型 -i鏡像文件 -o 轉(zhuǎn)換后文件輸出路徑
    
  4. 案例實(shí)操

    [root@linux121 current]$ cd /opt/lagou/servers/hadoop2.9.2/data/tmp/dfs/name/current
    [root@linux121 current]$ hdfs oiv -p XML -i fsimage_0000000000000000265 -o /opt/lagou/servers/fsimage.xml
    [root@linux121 current]$ cat /opt/lagou/servers/fsimage.xml
    
  5. 查看文件

    <?xml version="1.0"?>
    <fsimage>
        <version>
            <layoutVersion>-63</layoutVersion>
            <onDiskVersion>1</onDiskVersion>
            <oivRevision>826afbeae31ca687bc2f8471dc841b66ed2c6704</oivRevision>
        </version>
        <NameSection>
            <namespaceId>722925838</namespaceId>
            <genstampV1>1000</genstampV1>
            <genstampV2>1049</genstampV2>
            <genstampV1Limit>0</genstampV1Limit>
            <lastAllocatedBlockId>1073741873</lastAllocatedBlockId>
            <txid>621</txid>
        </NameSection>
        <INodeSection>
            <lastInodeId>16487</lastInodeId>
            <numInodes>36</numInodes>
            <inode>
                <id>16385</id>
                <type>DIRECTORY</type>
                <name></name>
                <mtime>1604115316122</mtime>
                <permission>root:supergroup:0777</permission>
                <nsquota>9223372036854775807</nsquota>
                <dsquota>-1</dsquota>
            </inode>
            <inode>
                <id>16389</id>
                <type>DIRECTORY</type>
                <name>wcinput</name>
                <mtime>1604023034981</mtime>
                <permission>root:supergroup:0777</permission>
                <nsquota>-1</nsquota>
                <dsquota>-1</dsquota>
            </inode> 
          </INodeSection>
    </fsimage>
    

    問(wèn)題: Fsimage 中為什么沒(méi)有記錄塊所對(duì)應(yīng) DataNode 青抛?

    答案:在集群?jiǎn)?dòng)后,NameNode 要求 DataNode 上報(bào)數(shù)據(jù)塊信息酬核,并間隔一段時(shí)間后再次上報(bào)

2.2 Edits文件內(nèi)容

  1. 基本語(yǔ)法

    hdfs oev -p 文件類(lèi)型 -i編輯日志 -o 轉(zhuǎn)換后文件輸出路徑
    
  2. 案例實(shí)操

    [root@linux121 current]$ hdfs oev -p XML -i edits_0000000000000000266-0000000000000000267 -o /opt/lagou/servers/hadoop-2.9.2/edits.xml
    [root@linux121 current]$ cat /opt/lagou/servers/hadoop-2.9.2/edits.xml
    
  3. 查看文件

    <?xml version="1.0" encoding="utf-8"?>
    
    <EDITS> 
      <EDITS_VERSION>-63</EDITS_VERSION>  
      <RECORD> 
        <OPCODE>OP_START_LOG_SEGMENT</OPCODE>  
        <DATA> 
          <TXID>113</TXID> 
        </DATA> 
      </RECORD>  
      <RECORD> 
        <OPCODE>OP_SET_PERMISSIONS</OPCODE>  
        <DATA> 
          <TXID>114</TXID>  
          <SRC>/wcoutput/_SUCCESS</SRC>  
          <MODE>493</MODE> 
        </DATA> 
      </RECORD>  
      <RECORD> 
        <OPCODE>OP_SET_PERMISSIONS</OPCODE>  
        <DATA> 
          <TXID>115</TXID>  
          <SRC>/wcoutput/part-r-00000</SRC>  
          <MODE>493</MODE> 
        </DATA> 
      </RECORD> 
    </EDITS>
    ...
    

    備注:Edits中只記錄了更新相關(guān)的操作蜜另,查詢或者下載文件并不會(huì)記錄在內(nèi)!!

    問(wèn)題: NameNode啟動(dòng)時(shí)如何確定加載哪些Edits?件呢?

    答案: 需要借助fsimage?件最后數(shù)字編碼,來(lái)確定哪些edits之前是沒(méi)有合并到fsimage中嫡意,啟動(dòng)時(shí)只需要加載那些未合并的edits?件即可举瑰。

3. checkpoint周期

  1. 通常情況下,SecondaryNameNode每隔一小時(shí)執(zhí)行一次蔬螟。

    官方默認(rèn)配置文件:hdfs-default.xml

    <property>
      <name>dfs.namenode.checkpoint.period</name>
      <value>3600</value>
    </property>
    
  2. 一分鐘檢查一次操作次數(shù)此迅,3當(dāng)操作次數(shù)達(dá)到1百萬(wàn)時(shí),SecondaryNameNode執(zhí)行一次。

    <property>
      <name>dfs.namenode.checkpoint.txns</name>
      <value>1000000</value>
    <description>操作動(dòng)作次數(shù)</description>
    </property>
    
    <property>
      <name>dfs.namenode.checkpoint.check.period</name>
      <value>60</value>
    <description> 1分鐘檢查一次操作次數(shù)</description>
    </property >
    

4. NameNode故障處理

NameNode故障后耸序,HDFS集群就無(wú)法正常工作忍些,因?yàn)镠DFS文件系統(tǒng)的元數(shù)據(jù)需要由NameNode來(lái)管理維護(hù)并與Client交互,如果元數(shù)據(jù)出現(xiàn)損壞和丟失同樣會(huì)導(dǎo)致NameNode?法正常?作進(jìn)?HDFS?件系統(tǒng)?法正常對(duì)外提供服務(wù)坎怪。

如果元數(shù)據(jù)出現(xiàn)丟失損壞如何恢復(fù)呢?

  1. 搭建HDFS的HA(?可用)集群罢坝,解決NN的單點(diǎn)故障問(wèn)題!!(借助Zookeeper實(shí)現(xiàn)HA,一個(gè) Active的NameNode,一個(gè)是Standby的NameNode)

  2. 將SecondaryNameNode中數(shù)據(jù)拷貝到NameNode存儲(chǔ)數(shù)據(jù)的目錄

    • kill -9 NameNode進(jìn)程

    • 刪除NameNode存儲(chǔ)的數(shù)據(jù)(/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name)

      [root@linux121 hadoop-2.9.2]rm -rf /opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name/*
      
    • 拷貝SecondaryNameNode中數(shù)據(jù)到原NameNode存儲(chǔ)數(shù)據(jù)目錄

      [root@linux121 hadoop-2.9.2]$ scp -r atguigu@hadoop104:/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/namesecondary/* ./name/
      
    • 重新啟動(dòng)NameNode

    [root@linux121 hadoop-2.9.2]$ sbin/hadoop-daemon.sh start namenode
    
  3. 使用-importCheckpoint選項(xiàng)啟動(dòng)NameNode守護(hù)進(jìn)程搅窿,從而將SecondaryNameNode中數(shù)據(jù)拷貝到NameNode目錄中炸客。

    • 修改hdfs-site.xml中的

      <property>
        <name>dfs.namenode.checkpoint.period</name>
        <value>120</value>
      </property>
      
      <property>
        <name>dfs.namenode.name.dir</name>
        <value>/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name</value>
      </property>
      
      
    • kill -9 NameNode進(jìn)程

    • 刪除NameNode存儲(chǔ)的數(shù)據(jù)(/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name)

      [root@linux121 hadoop-2.9.2]rm -rf /opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name/*
      
    • 如果SecondaryNameNode不和NameNode在一個(gè)主機(jī)節(jié)點(diǎn)上,需要將SecondaryNameNode存儲(chǔ)數(shù)據(jù)的目錄拷貝到NameNode存儲(chǔ)數(shù)據(jù)的平級(jí)目錄戈钢,并刪除in_use.lock文件

      [root@linux123 dfs]$ scp -r root@linux121:/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/namesecondary ./
      
      [root@linux123 namesecondary]$ rm -rf in_use.lock
      
      [root@linux123 dfs]$ pwd
      /opt/lagou/servers/hadoop-2.9.2//data/tmp/dfs
      
      [root@linux123 dfs]$ ls
      data  name  namesecondary
      
      
    • 導(dǎo)入檢查點(diǎn)數(shù)據(jù)(等待一會(huì)ctrl+c結(jié)束掉)

      [root@linux121 hadoop-2.9.2]$ bin/hdfs namenode -importCheckpoint
      
    • 啟動(dòng)NameNode

      [root@linux121 hadoop-2.9.2]$ sbin/hadoop-daemon.sh start namenode
      

五、Hadoop的限額與歸檔以及集群安全模式

1. HDFS?件限額配置

HDFS文件的限額配置允許我們以?件?小或者文件個(gè)數(shù)來(lái)限制我們?cè)谀硞€(gè)目錄下上傳的文件數(shù)量或者文件內(nèi)容總量是尔,以便達(dá)到我們類(lèi)似百度網(wǎng)盤(pán)等限制每個(gè)?戶允許上傳的最大的?件的量

  1. 數(shù)量限額

    #創(chuàng)建hdfs?件夾
    hdfs dfs -mkdir -p /user/root/lagou
    
    # 給該?件夾下?設(shè)置最多上傳兩個(gè)文件殉了,上傳?件,發(fā)現(xiàn)只能上傳一個(gè)文件
    hdfs dfsadmin -setQuota 2 /user/root/lagou 
    
    # 清除文件數(shù)量限制
    hdfs dfsadmin -clrQuota /user/root/lagou
    
  2. 空間?小限額

    # 限制空間?小4KB
    hdfs dfsadmin -setSpaceQuota 4k /user/root/lagou
    
    #上傳超過(guò)4Kb的?件?小上去提示文件超過(guò)限額
    hdfs dfs -put /export/softwares/xxx.tar.gz /user/root/lagou
    
    #清除空間限額
    hdfs dfsadmin -clrSpaceQuota /user/root/lagou
    
    #查看hdfs?件限額數(shù)量
    hdfs dfs -count -q -h /user/root/lagou
    

2. HDFS的安全模式

  1. 安全模式是HDFS所處的一種特殊狀態(tài)拟枚,在這種狀態(tài)下薪铜,<font color=red>文件系統(tǒng)只接受讀數(shù)據(jù)請(qǐng)求,而不接受刪除恩溅、修改等變更請(qǐng)求</font>隔箍。在NameNode主節(jié)點(diǎn)啟動(dòng)時(shí),HDFS?先進(jìn)入安全模式脚乡,DataNode在啟動(dòng)的時(shí)候會(huì)向NameNode匯報(bào)可用的block等狀態(tài)蜒滩,當(dāng)整個(gè)系統(tǒng)達(dá)到安全標(biāo)準(zhǔn)時(shí),HDFS自動(dòng)離開(kāi)安全模式奶稠。如果HDFS出于安全模式下俯艰,則文件block不能進(jìn)行任何的副本復(fù)制操作,因此達(dá)到最?的副本數(shù)量要求是基于DataNode啟動(dòng)時(shí)的狀態(tài)來(lái)判定的锌订,啟動(dòng)時(shí)不會(huì)再做任何復(fù)制(從?達(dá)到最?副本數(shù)量要求)竹握,HDFS集群剛啟動(dòng)的時(shí)候,默認(rèn)30S鐘的時(shí)間是出于安全期的辆飘,只有過(guò)了30S之后啦辐,集群脫離了了安全期,然后才可以對(duì)集群進(jìn)行操作蜈项。
  2. 相關(guān)命令:hdfs dfsadmin -safemode

3. Hadoop歸檔技術(shù)

  1. 主要解決HDFS集群存在?量?文件的問(wèn)題!!

    由于?量?文件會(huì)占?NameNode的內(nèi)存芹关,因此對(duì)于HDFS來(lái)說(shuō)存儲(chǔ)?量?文件造成NameNode內(nèi)存資源的浪費(fèi)!

  2. Hadoop存檔?件HAR文件,是?個(gè)更高效的文件存檔工具紧卒,HAR?件是由?組文件通過(guò)archive?具創(chuàng)建?來(lái)充边,在減少了NameNode的內(nèi)存使?的同時(shí),可以對(duì)文件進(jìn)行透明的訪問(wèn),通俗來(lái)說(shuō)就是HAR?件對(duì)NameNode來(lái)說(shuō)是?個(gè)?件減少了內(nèi)存的浪費(fèi)浇冰,對(duì)于實(shí)際操作處理文件依然是一個(gè)?個(gè)獨(dú)立的文件贬媒。
  1. 案例

    1. 啟動(dòng)YARN集群

      [root@linux121 hadoop-2.9.2]$ start-yarn.sh
      
    2. 歸檔文件

      把/user/lagou/input?錄?面的所有?件歸檔成?個(gè)叫input.har的歸檔?件,并把歸檔后文件存儲(chǔ)到/user/lagou/output路徑下肘习。

       [root@linux121 hadoop-2.9.2]$ bin/hadoop archive -archiveName input.har –p /user/root/input  /user/root/output
      
    3. 查看歸檔

      [root@linux121 hadoop-2.9.2]$ hadoop fs -lsr /user/root/output/input.har
      [root@linux121 hadoop-2.9.2]$ hadoop fs -lsr har:///user/root/output/input.har
      
    4. 解歸檔?件

      [root@linux121 hadoop-2.9.2]$ hadoop fs -cp har:///user/root/output/input.har/*  /user/root
      

六际乘、DataNode

1. DataNode工作機(jī)制

DataNode工作機(jī)制:

  1. 一個(gè)數(shù)據(jù)塊在DataNode上以文件形式存儲(chǔ)在磁盤(pán)上,包括兩個(gè)文件漂佩,一個(gè)是數(shù)據(jù)本身脖含,一個(gè)是元數(shù)據(jù)包括數(shù)據(jù)塊的長(zhǎng)度,塊數(shù)據(jù)的校驗(yàn)和投蝉,以及時(shí)間戳养葵。
  2. DataNode啟動(dòng)后向NameNode注冊(cè),通過(guò)后瘩缆,周期性(1小時(shí))的向NameNode上報(bào)所有的塊信息关拒。
  3. 心跳是每3秒一次,心跳返回結(jié)果帶有NameNode給該DataNode的命令如復(fù)制塊數(shù)據(jù)到另一臺(tái)機(jī)器庸娱,或刪除某個(gè)數(shù)據(jù)塊着绊。如果超過(guò)10分鐘沒(méi)有收到某個(gè)DataNode的心跳,則認(rèn)為該節(jié)點(diǎn)不可用熟尉。
  4. 集群運(yùn)行中可以安全加入和退出一些機(jī)器归露。

2. 數(shù)據(jù)完整性

  1. 思考:

    如果電腦磁盤(pán)里面存儲(chǔ)的數(shù)據(jù)是控制高鐵信號(hào)燈的紅燈信號(hào)(1)和綠燈信號(hào)(0),但是存儲(chǔ)該數(shù)據(jù)的磁盤(pán)壞了斤儿,一直顯示是綠燈剧包,是否很危險(xiǎn)?同理DataNode節(jié)點(diǎn)上的數(shù)據(jù)損壞了往果,卻沒(méi)有發(fā)現(xiàn)玄捕,是否也很危險(xiǎn),那么如何解決呢棚放?

  2. DataNode節(jié)點(diǎn)保證數(shù)據(jù)完整性的方法:

    1. 當(dāng)DataNode讀取Block的時(shí)候枚粘,它會(huì)計(jì)算CheckSum。
    2. 如果計(jì)算后的CheckSum飘蚯,與Block創(chuàng)建時(shí)值不一樣馍迄,說(shuō)明Block已經(jīng)損壞。
    3. Client讀取其他DataNode上的Block局骤。
    4. DataNode在其文件創(chuàng)建后周期驗(yàn)證CheckSum攀圈,如下圖所示。
      image-20201130182018827.png

3. 掉線時(shí)限參數(shù)設(shè)置

  1. DataNode進(jìn)程死亡或者網(wǎng)絡(luò)故障造成DataNode無(wú)法與NameNode通信

  2. NameNode不會(huì)立即把該節(jié)點(diǎn)判定為死亡峦甩,要經(jīng)過(guò)一段時(shí)間赘来,這段時(shí)間暫稱作超時(shí)時(shí)長(zhǎng)现喳。

  3. HDFS默認(rèn)的超時(shí)時(shí)長(zhǎng)為10分鐘+30秒。

  4. 如果定義超時(shí)時(shí)間為T(mén)imeOut犬辰,則超時(shí)時(shí)長(zhǎng)的計(jì)算公式為:

    TimeOut  = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval嗦篱。
    
    而默認(rèn)的dfs.namenode.heartbeat.recheck-interval 大小為5分鐘,dfs.heartbeat.interval默認(rèn)為3秒幌缝。
    

注意:

  • hdfs-site.xml 配置文件中的heartbeat.recheck.interval的單位為<font color=red>毫秒</font>灸促,dfs.heartbeat.interval的單位為<font color=red>秒</font>

  • <property>
        <name>dfs.namenode.heartbeat.recheck-interval</name>
        <value>300000</value>
    </property>
    <property>
        <name>dfs.heartbeat.interval</name>
        <value>3</value>
    </property>
    

對(duì)大數(shù)據(jù)感興趣的小伙伴可以關(guān)注我的公眾號(hào):大數(shù)據(jù)學(xué)習(xí)寶典涵卵,在上面會(huì)定期更新學(xué)習(xí)筆記和一些心得浴栽!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市轿偎,隨后出現(xiàn)的幾起案子典鸡,更是在濱河造成了極大的恐慌,老刑警劉巖坏晦,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萝玷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡英遭,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)亦渗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)挖诸,“玉大人,你說(shuō)我怎么就攤上這事法精《嗦桑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵搂蜓,是天一觀的道長(zhǎng)狼荞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)帮碰,這世上最難降的妖魔是什么相味? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮殉挽,結(jié)果婚禮上丰涉,老公的妹妹穿的比我還像新娘。我一直安慰自己斯碌,他們只是感情好一死,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著傻唾,像睡著了一般投慈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天伪煤,我揣著相機(jī)與錄音加袋,去河邊找鬼。 笑死带族,一個(gè)胖子當(dāng)著我的面吹牛锁荔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蝙砌,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼阳堕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了择克?” 一聲冷哼從身側(cè)響起恬总,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肚邢,沒(méi)想到半個(gè)月后壹堰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡骡湖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年贱纠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片响蕴。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谆焊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出浦夷,到底是詐尸還是另有隱情辖试,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布劈狐,位于F島的核電站罐孝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏肥缔。R本人自食惡果不足惜莲兢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望续膳。 院中可真熱鬧怒见,春花似錦、人聲如沸姑宽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)炮车。三九已至舵变,卻和暖如春酣溃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纪隙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工赊豌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绵咱。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓碘饼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親悲伶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艾恼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容