Hadoop

HDFS文件系統(tǒng)

HDFS是一個分布式文件系統(tǒng),采用分而治之的設計思想哼勇,將大文件个初、大批量文件,分布式存放在大量服務器上猴蹂,為各類分布式運算框架(MapReduce,spark楣嘁,tez等)提供數(shù)據(jù)存儲服務磅轻。首先,它是一個文件系統(tǒng)逐虚,用于存儲文件聋溜,通過統(tǒng)一的命名空間目錄樹來定位文件,對用戶來說叭爱,DataNode是透明的撮躁,HDFS相當于是提供了一個統(tǒng)一的目錄結構,用戶上傳的文件的適合买雾,只需要和這個統(tǒng)一的目錄結構打交道把曼,雖然實際上用戶的文件被切成不同的block存放在了不同的DataNode上,這部分元信息被存放在NameNode中漓穿;其次嗤军,它是分布式的,由很多服務器聯(lián)合起來實現(xiàn)其功能晃危,集群中的服務器有各自的角色叙赚。

虛擬機網(wǎng)絡配置

HDFS

基本特性

適合用來做數(shù)據(jù)分析,并不適合用來做網(wǎng)盤應用僚饭,因為震叮,不便修改,延遲大鳍鸵,網(wǎng)絡開銷大苇瓣,成本太高

  1. HDFS中的文件在物理上是分塊存儲(block),塊的大小可以通過配置參數(shù)(dfs.blocksize)來規(guī)定权纤,默認大小在hadoop2.x版本中是128M钓简,老版本中是64M乌妒;
  2. HDFS文件系統(tǒng)會給客戶端提供一個統(tǒng)一的抽象目錄樹,客戶端通過路徑來訪問文件外邓,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data撤蚊;
  3. 目錄結構及文件分塊信息(元數(shù)據(jù))的管理由NameNode節(jié)點承擔。NameNode是HDFS集群主節(jié)點损话,負責維護整個hdfs文件系統(tǒng)的目錄樹侦啸,以及每一個路徑(文件)所對應的block塊信息(block的id,及所在的DataNode服務器)丧枪;
  4. 文件的各個block的存儲管理由DataNode節(jié)點承擔光涂。DataNode是HDFS集群從節(jié)點,每一個block都可以在多個DataNode上存儲多個副本(副本數(shù)量也可以通過參數(shù)設置dfs.replication)拧烦;
  5. HDFS是設計成適應一次寫入忘闻,多次讀出的場景,且不支持文件的修改恋博;

常見命令

// 列出文件
hadoop fs -ls /

// 創(chuàng)建目錄
hadoop fs -mkdir 目錄名稱

// 查看文件
hadoop fs -cat 文件名稱

// 刪除文件或文件夾
hadoop fs -rm -r /aaa/bbb/

// 從本地文件系統(tǒng)中拷貝文件到hdfs路徑去
hadoop  fs  -copyFromLocal  ./jdk.tar.gz  /aaa/
// 上傳齐佳,等同于copyFromLocal
hadoop  fs  -put  /aaa/jdk.tar.gz  /bbb/jdk.tar.gz.2

// 從hdfs拷貝到本地
hadoop fs -copyToLocal /aaa/jdk.tar.gz
// 從hdfs下載文件到本地,等同于copyToLocal 
hadoop fs -get  /aaa/jdk.tar.gz

// 統(tǒng)計文件系統(tǒng)的可用空間信息
hadoop  fs  -df  -h  /

// 統(tǒng)計文件夾的大小信息
hadoop  fs  -du  -s  -h /aaa/*

// 統(tǒng)計一個指定目錄下的文件節(jié)點數(shù)量
hadoop fs -count /aaa/

// 設置hdfs中文件的副本數(shù)量债沮,這里設置的副本數(shù)只是記錄在NameNode的元數(shù)據(jù)中炼吴,是否真的會有這么多副本,還得看DataNode的數(shù)量
hadoop fs -setrep 3 /aaa/jdk.tar.gz

常用參數(shù)

hdfs-site.xml

// 每個block塊的大小疫衩,默認128M
dfs.blocksize

// 文件副本個數(shù)
dfs.replication

工作機制

  1. HDFS集群分為兩大角色:NameNode硅蹦、DataNode;
  2. NameNode負責管理整個文件系統(tǒng)的元數(shù)據(jù)闷煤;
  3. DataNode負責管理用戶的文件數(shù)據(jù)塊童芹;
  4. 文件會按照固定的大小(blocksize)切成若干塊后分布式存儲在若干臺DataNode上;
  5. 每一個文件塊可以有多個副本曹傀,并存放在不同的DataNode上辐脖;
  6. DataNode會定期向NameNode匯報自身所保存的文件block信息,而NameNode則會負責保持文件的副本數(shù)量皆愉;
  7. HDFS的內(nèi)部工作機制對客戶端保持透明嗜价,客戶端請求訪問HDFS都是通過向NameNode申請來進行;

NameNode機制

NameNode職責:負責客戶端請求的響應幕庐;元數(shù)據(jù)的管理(查詢久锥,修改);

NameNode對數(shù)據(jù)的管理采用了三種存儲形式:

  • 內(nèi)存元數(shù)據(jù)(NameSystem)异剥;
  • 磁盤元數(shù)據(jù)鏡像文件瑟由;
  • 數(shù)據(jù)操作日志文件(可通過日志運算出元數(shù)據(jù));
元數(shù)據(jù)管理機制
  • 內(nèi)存中有一份完整的元數(shù)據(jù):內(nèi)存meta data冤寿;
  • 磁盤有一個“準完整”的元數(shù)據(jù)鏡像:fsimage歹苦,文件存在于NameNode的工作目錄中青伤;
  • 用于銜接內(nèi)存metadata和持久化元數(shù)據(jù)鏡像fsimage之間的操作日志:edits文件,當客戶端對HDFS中的文件進行新增或者修改操作殴瘦,操作記錄首先被記入edits日志文件中狠角,當客戶端操作成功后,相應的元數(shù)據(jù)會更新到內(nèi)存meta.data中蚪腋;
元數(shù)據(jù)checkpoint

每隔一段時間丰歌,會由SecondaryNameNode將NameNode上積累的所有edits和一個最新的fsimage下載到本地,并加載到內(nèi)存進行merge屉凯,這個過程稱為checkpoint立帖。
NameNode和SecondaryNameNode的工作目錄存儲結構完全相同,所以悠砚,當NameNode故障退出需要重新恢復時晓勇,可以從SecondaryNameNode的工作目錄中將fsimage拷貝到NameNode的工作目錄值依,以恢復NameNode的元數(shù)據(jù)役首。

checkpoint參數(shù)
dfs.namenode.checkpoint.check.period=60  #檢查觸發(fā)條件是否滿足的頻率,60秒
dfs.namenode.checkpoint.dir=file://${hadoop.tmp.dir}/dfs/namesecondary
#以上兩個參數(shù)做checkpoint操作時辩棒,secondary namenode的本地工作目錄
dfs.namenode.checkpoint.edits.dir=${dfs.namenode.checkpoint.dir}

dfs.namenode.checkpoint.max-retries=3  #最大重試次數(shù)
dfs.namenode.checkpoint.period=3600  #兩次checkpoint之間的時間間隔3600秒
dfs.namenode.checkpoint.txns=1000000 #兩次checkpoint之間最大的操作記錄

DataNode機制

Datanode工作職責:存儲管理用戶的文件塊數(shù)據(jù)节榜;定期向NameNode匯報自身所持有的block信息(通過心跳信息上報),這點很重要别智,因為當集群中發(fā)生某些block副本失效時宗苍,集群如何恢復block初始副本數(shù)量的問題。

<property>
    <name>dfs.blockreport.intervalMsec</name>
    <value>3600000</value>
    <description>Determines block reporting interval in milliseconds.</description>
</property>
DataNode掉線判斷時限參數(shù)

DataNode進程死亡或者網(wǎng)絡故障造成DataNode無法與NameNode通信薄榛,NameNode不會立即把該節(jié)點判定為死亡讳窟,要經(jīng)過一段時間,這段時間暫稱作超時時長敞恋。HDFS默認的超時時長為10分鐘+30秒丽啡。如果定義超時時間為timeout,則超時時長的計算公式為:

timeout  = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval

而默認的heartbeat.recheck.interval 大小為5分鐘硬猫,dfs.heartbeat.interval默認為3秒补箍。
需要注意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的單位為毫秒,dfs.heartbeat.interval的單位為秒啸蜜。所以坑雅,舉個例子,如果heartbeat.recheck.interval設置為5000(毫秒)衬横,dfs.heartbeat.interval設置為3(秒裹粤,默認),則總的超時時間為40秒蜂林。

<property>
    <name>heartbeat.recheck.interval</name>
    <value>2000</value>
</property>
<property>
    <name>dfs.heartbeat.interval</name>
    <value>1</value>
</property>

文件上傳機制

用戶上傳的文件遥诉,被切成諾干個block塊存放在不同的DataNode中拇泣,并且每個文件都會在集群中存儲多個文件副本,副本的數(shù)量可以由用戶指定矮锈。至于文件被切成多少個block快霉翔,每個塊在哪臺DataNode上,這部分元信息存儲在NameNode中愕难。
客戶端要向HDFS寫數(shù)據(jù)早龟,首先要跟NameNode通信以確認可以寫文件并獲得接收文件block的DataNode,然后猫缭,客戶端按順序?qū)⑽募饌€block傳遞給相應DataNode葱弟,并由接收到block的DataNode負責向其他DataNode復制block的副本。

  1. 根NameNode通信請求上傳文件猜丹,NameNode檢查目標文件是否已存在芝加,父目錄是否存在;
  2. NameNode返回是否可以上傳射窒;
  3. client請求第一個block該傳輸?shù)侥男ヾatanode服務器上藏杖;
  4. NameNode返回3個DataNode服務器ABC;
  5. client請求3臺dn中的一臺A上傳數(shù)據(jù)(本質(zhì)上是一個RPC調(diào)用脉顿,建立pipeline)蝌麸,A收到請求會繼續(xù)調(diào)用B,然后B調(diào)用C艾疟,將真?zhèn)€pipeline建立完成来吩,逐級返回客戶端;
  6. client開始往A上傳第一個block(先從磁盤讀取數(shù)據(jù)放到一個本地內(nèi)存緩存)蔽莱,以packet為單位弟疆,A收到一個packet就會傳給B,B傳給C盗冷;A每傳一個packet會放入一個應答隊列等待應答怠苔;
  7. 當一個block傳輸完成之后,client再次請求NameNode上傳第二個block的服務器仪糖;

文件下載機制

客戶端將要讀取的文件路徑發(fā)送給NameNode柑司,NameNode獲取文件的元信息(主要是block的存放位置信息)返回給客戶端,客戶端根據(jù)返回的信息找到相應DataNode逐個獲取文件的block并在客戶端本地進行數(shù)據(jù)追加合并從而獲得整個文件锅劝。

  1. 跟NameNode通信查詢元數(shù)據(jù)帜羊,找到文件塊所在的DataNode服務器;
  2. 挑選一臺DataNode(就近原則鸠天,然后隨機)服務器讼育,請求建立socket流;
  3. DataNode開始發(fā)送數(shù)據(jù)(從磁盤里面讀取數(shù)據(jù)放入流,以packet為單位來做校驗)奶段;
  4. 客戶端以packet為單位接收饥瓷,現(xiàn)在本地緩存,然后寫入目標文件痹籍;

HDFS客戶端編程場景

  • 數(shù)據(jù)采集

YARN

運算資源調(diào)度呢铆。
MapReduce程序應該是在很多機器上并行啟動,而且先執(zhí)行MapTask蹲缠,當眾多的MapTask都處理完自己的數(shù)據(jù)后棺克,還需要啟動眾多的ReduceTask,這個過程如果用用戶自己手動調(diào)度不太現(xiàn)實线定,需要一個自動化的調(diào)度平臺娜谊,hadoop中就為運行MapReduce之類的分布式運算程序開發(fā)了一個自動化調(diào)度平臺:YARN。

YARN集群中有兩個角色:1臺 ResourceManager 和 N臺 NodeManager斤讥。ResourceManager一般安裝在一臺專門的機器上纱皆,NodeManager應該與HDFS中的DataNode重疊在一起。
yarn-site.xml

<property>
    <name>yarn.resourcemanager.hostname</name>
    <value>hdp-04</value>
</property>

<property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
</property>

Linux環(huán)境準備

接下來主要介紹Hadoop集群環(huán)境的搭建過程芭商,實際應用中應該不會這樣做派草,而是通過一些管理工具進行安裝,比如可視化安裝:Ambari铛楣。


虛擬機鏡像
軟件安裝包

前置條件

  • CentOS7

  • Oracle VM VirtualBox

安裝過程

這就相當于通過虛擬機搭建一個局域網(wǎng)近迁,安裝配置過程已經(jīng)截圖并整理成PPT。主要需要注意的地方就是網(wǎng)絡的配置簸州,我這里通過配置兩個網(wǎng)卡來實現(xiàn):一個用于訪問外部網(wǎng)絡(NAT)钳踊;一個用于和window主機交互(Host-Only)。



我的系統(tǒng)是centos7

vi /etc/sysconfig/network-scripts/ifcfg-enp0s3

配置文件修改成以下內(nèi)容

TYPE=Ethernet

PROXY_METHOD=none

BROWSER_ONLY=no

BOOTPROTO=static

DEFROUTE=yes

IPV4_FAILURE_FATAL=no

IPV6INIT=yes

NAME=enp0s3

UUID=4704faea-0e23-4ad9-a06c-3e37e577636c

DEVICE=enp0s3

ONBOOT=yes

NM_CONTROLLED=yes

IPADDR=192.168.88.21

虛擬機安裝過程

基礎配置

添加用戶

分別在三臺服務器上執(zhí)行創(chuàng)建 haddop用戶勿侯,同時設置密碼為hadoop

useradd hadoop

passwd hadoop

創(chuàng)建用戶之后切換為hadoop用戶登錄,我們所有的操作都基于hadoop用戶

配置host

分別在三臺服務器配置host

vi /etc/hosts

添加以下內(nèi)容

192.168.88.21 master

192.168.88.22 slave1

192.168.88.23 slave2

配置免密登錄

分別在三臺機器上安裝 openssh-server

yum install openssh-server

分別在三臺機器上執(zhí)行以下命令

mkdir .ssh
chmod 700 .ssh
ssh-keygen -t rsa
cp id_rsa.pub authorized_keys
chmod 600 authorized_keys

在 22 服務器執(zhí)行

scp /home/hadoop/.ssh/id_rsa.pub hadoop@master:/home/hadoop/.ssh/id_rsa.pub.slave1

在 23 服務器執(zhí)行

scp /home/hadoop/.ssh/id_rsa.pub hadoop@master:/home/hadoop/.ssh/id_rsa.pub.slave2

在 21 服務器執(zhí)行

cat id_rsa.pub.slave1 >> authorized_keys

cat id_rsa.pub.slave2 >> authorized_keys

scp /home/hadoop/.ssh/authorized_keys hadoop@slave1:/home/hadoop/.ssh/authorized_keys

scp /home/hadoop/.ssh/authorized_keys hadoop@slave2:/home/hadoop/.ssh/authorized_keys

至此配置完成缴罗,接下來是測試:

在 21 服務器執(zhí)行

ssh salve1
ssh salve2

有個問題助琐,之前配置好了之后還是不停提示要輸入密鑰,然后安裝了 openssh-server 之后面氓,再測試就可以了兵钮,不知道是不是這個的影響。

配置JDK

jdk-8u171-linux-x64.tar.gz

在/home/hadoop 目錄下創(chuàng)建java文件夾

mkdir java

在java 目錄內(nèi)解壓安裝包

tar -zxvf jdk-8u171-linux-x64.tar.gz

然后分別拷貝到兩臺slave

scr -r jdk1.8 hadoop@slave1:/home/hadoop
scr -r jdk1.8 hadoop@slave2:/home/hadoop

分別在三臺機器上配置JAVA_HOME

export JAVA_HOME=/home/hadoop/jdk1.8

export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar

:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

export PATH=$PATH:$JAVA_HOME/bin

測試:

執(zhí)行 java -version 看控制臺輸出

其它配置

修改windos下的hosts文件舌界,因為到時候再瀏覽器上訪問的時候會用到域名

C:\WINDOWS\System32\drivers\etc\hosts

192.168.88.21 master

192.168.88.22 slave1

192.168.88.23   slave2

修改linux系統(tǒng)的hostname掘譬,注意不是修改/etc/hoss文件,centos7永久修改hostname使用以下命令

hostnamectl set-hostname 名稱

安裝Hadoop

下載安裝

1呻拌、官網(wǎng)下載葱轩,這個地址下載有點慢

http://apache.claz.org

2、以下的地址下載更快一些

http://mirror.bit.edu.cn/apache/

http://mirror.bit.edu.cn/apache/

https://mirrors.tuna.tsinghua.edu.cn/apache/

我最終下載的版本是:hadoop-2.7.6.tar.gz

安裝過程很簡單,只需要直接解壓就可以了靴拱。

三臺機器機器最終的配置基本一樣垃喊,所以我們只需要在一臺機器上配置好,然后拷貝到其它機器就好袜炕, 這里是在master機器上配置本谜。

在master上執(zhí)行以下命令

cd /home/Hadoop

mkdir -p cludata/hadoop

cd cludata/hadoop

mkdir -p hdfs/data hdfs/name temp

tar -zxvf hadoop-2.7.6.tar.gz

HADOOP_HOME

就是配置hadoop環(huán)境變量,這個需要在三臺機器上分別執(zhí)行

vi ~/.bash_profile

export HADOOP_HOME=/home/hadoop/hadoop-2.7.6

export PATH=$PATH:$JAVA_HOME/bin::$HADOOP_HOME/bin:$HADOOP_HOME/sbin

配置文件

主要需要配置以下幾個配置文件:core-site.xml偎窘、hdfs-site.xml乌助、mapred-site.xml和yarn-site.xml、slaves陌知。然后可能還需要再hadoop-env.sh中添加JAVA環(huán)境變量他托。

以下配置文件可作為參考,還有很多其它配置項纵诞。

  • core-site.xml

該配置文件主要用于定義系統(tǒng)級別的參數(shù)上祈,如HDFS、URL浙芙、hadoop的臨時目錄

<configuration>
  <property>
    <name>fs.default.name</name>
    <value>hdfs://master:9000</value>
    <description>文件系統(tǒng)主機和端口</description>   
  </property>
  <property>
    <name>io.file.buffer.size</name>
    <value>131072</value>
    <description>每個block的大小</description>
  </property>
  <property>
    <name>hadoop.tmp.dir</name>
    <value>file:/home/hadoop/cludata/hadoop/temp</value>
    <description>臨時目錄</description>   
  </property>
</configuration>
  • dfs-site.xml
<configuration>
  <property>
    <name>dfs.namenode.secondary.http-address</name>
    <value>master:9001</value>
    <description>通過web界面來查看HDFS狀態(tài)</description>
  </property>
  <property>
    <name>dfs.namenode.name.dir</name> 
    <value>file:/home/hadoop/cludata/hadoop/hdfs/name</value>
  </property>
  <property>
    <name>dfs.datanode.data.dir</name>  
    <value>file:/home/hadoop/cludata/hadoop/hdfs/data</value>
  </property>
  <property>
    <name>dfs.replication</name>
    <value>3</value>
    <description>每個Block有2個備份</description>
  </property>
  <property>
    <name>dfs.webhdfs.enabled</name>
    <value>true</value>
    <description>是否通過http協(xié)議訪問hdfs文件</description>
  </property>
</configuration>
  • mapred-site.xml
<configuration>
  <property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
  </property>
  <property>
    <name>mapreduce.jobhistory.address</name>
    <value>master:10020</value>
  </property>
  <property>
    <name>mapreduce.jobhistory.webapp.address</name>
    <value>master:19888</value>
  </property>
</configuration>
  • yarn-site.xml
<configuration>
  <!-- Site specific YARN configuration properties -->
  <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
  </property>
  <property>
    <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
    <value>org.apache.hadoop.mapred.ShuffleHandler</value>
  </property>
  <property>
    <name>yarn.resourcemanager.address</name>
    <value>master:8032</value>
  </property>
  <property>
    <name>yarn.resourcemanager.scheduler.address</name>
    <value>master:8030</value>
  </property>
  <property>
    <name>yarn.resourcemanager.resource-tracker.address</name>
    <value>master:8031</value>
  </property>
  <property>
    <name>yarn.resourcemanager.admin.address</name>
    <value>master:8033</value>
  </property>
  <property>
    <name>yarn.resourcemanager.webapp.address</name>
    <value>master:8088</value>
  </property>
  <property>
    <name>yarn.nodemanager.resource.memory-mb</name>
    <value>8192</value>
  </property>
</configuration>
  • slaves

這個配置文件主要是配置 datanode

把localhost去掉登刺,添加以下內(nèi)容

slave1

slave2

配置完成之后,將整個hadoop文件夾拷貝到其它兩臺機器

cd /home/hadoop

scp -r hadoop-2.7.6 hadoop@slave1:/home/hadoop/

scp -r hadoop-2.7.6 hadoop@slave2:/home/hadoop/

格式化

在啟動hadoop之前嗡呼,需要先格式化HDFS文件系統(tǒng)纸俭,只需要在master上執(zhí)行即可

hadoop namenode -format
格式化

啟動

有關于hadoop的一些腳本命令,存放在根目錄下的sbin 文件夾下:即/home/hadoop /hadoop-2.7.6/sbin


腳本命令

所以南窗,先進入sbin目錄

cd /home/hadoop /hadoop-2.7.6/sbin
  • 啟動NameNode
hadoop-daemon.sh start namenode

執(zhí)行該命令后可以通過 ps -ef|grep hadoop 命令查看hadoop進程揍很,也可以使用jsp命令查看JVM進行。運行jsp命令之后万伤,可以可能到 Namenode進程窒悔。


  • 啟動DataNode
hadoop-daemon.sh start datanode

在master上執(zhí)行該命令后,在兩臺slave上分別執(zhí)行 jps 命令查看 datanode是否啟動敌买,如果發(fā)現(xiàn) Datanode 進程說明啟動成功简珠。


提示:其實以上兩個啟動過程可以通過一個腳本來啟動,hadoop里面也提供了這個腳本虹钮,也是在sbin目錄中聋庵,只要執(zhí)行這個腳本就可以了

./start-dfs.sh

//對應的停止命令

./stop-dfs.sh
  • 啟動ResourceManager
yarn-daemon.sh start resourcemanager

執(zhí)行該命令之后,使用jsp命令可以查看到ResourceManager說明啟動成功芙粱。

  • 啟動NodeManager
yarn-daemon.sh start nodemanager

同理祭玉,通過jpps命令可以看到 NodeManage進程。

注意:以上兩個過程也可以通過一個腳本來啟動

./start-yarn.sh

//對應的停止命令

./stop-yarn.sh
  • 瀏覽器訪問

http://192.168.88.21:50070

可以看到以下界面


hadoop

http://192.168.88.21:8088

可以看到以下界面


yarn

常見命令

hadoop下有一些常見命令

列出文件:hadoop fs -ls /

創(chuàng)建目錄:hadoop fs -mkdir 目錄

上傳文件:hadoop fs -put filename 目錄

查看文件:hadoop fs -cat 文件

測試案例

啟動之后春畔,可以用hadoop來處理一個demo脱货,這個demo程序是hadoop在安裝包里面已經(jīng)提供了岛都。

hadoop jar /home/hadoop/hadoop-2.7.6/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.6.jar pi 5 10

Pi 5 10 表示開 5個Map , 10 個 Reduce

執(zhí)行這命令之后蹭劈,控制臺會有一系列輸出疗绣,同時在瀏覽器上也可以看到效果

http://192.168.88.21:8088

MapReducer

其實上面就是一個Map Reducer 程序,這是官方提供的一個Demo铺韧,不過我們好像并不是很清楚這個程序的運行機制是什么樣的多矮,所以在此之前,有必要了解一下MapReducer哈打。MapReducer可以在任何地方運行程序塔逃,訪問HDFS上的文件并進行統(tǒng)計運算,并且可以把統(tǒng)計的結果寫回HDFS的結果文件中料仗。包括接下來介紹了HIVE湾盗,其實內(nèi)部也是基于MapReducer實現(xiàn),只不過HIVE內(nèi)部進行了大量封裝立轧,所以我們才可以寫SQL語句格粪,其實每條SQL語句,都可以看成是一個MapReducer程序氛改。MapReducer中有兩個概念:Map 和 Reducer帐萎。

Map階段: 將每一行文本數(shù)據(jù)變成<單詞,1>這樣的kv數(shù)據(jù)

Reduce階段:將相同單詞的一組kv數(shù)據(jù)進行聚合:累加所有的v

下面是一個簡單WordCount 示例

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hand.sxy</groupId>
    <artifactId>MapReducer</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.6</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-core</artifactId>
            <version>2.7.6</version>
        </dependency>
    </dependencies>

</project>

WordCount.java

package com.hand.sxy;

import com.hand.sxy.utils.FileUtil;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;

public class WordCount {

    public static void main(String[] args) throws Exception {

        FileUtil.deleteDir("/output");
        Configuration conf = new Configuration();

        String[] otherArgs = new String[]{"hdfs://master:9000/test/dream.txt", "/output"};
        if (otherArgs.length != 2) {
            System.err.println("Usage:Merge and duplicate removal <in> <out>");
            System.exit(2);
        }

        Job job = Job.getInstance(conf, "WordCount");
        job.setJarByClass(WordCount.class);
        job.setMapperClass(WordCount.TokenizerMapper.class);
        job.setReducerClass(WordCount.IntSumReduce.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
        FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }


    public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> {

        public static final IntWritable one = new IntWritable(1);
        private Text word = new Text();

        public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
            StringTokenizer itr = new StringTokenizer(value.toString());
            while (itr.hasMoreTokens()) {
                this.word.set(itr.nextToken());
                context.write(this.word, one);
            }
        }

    }

    public static class IntSumReduce extends Reducer<Text, IntWritable, Text, IntWritable> {
        private IntWritable result = new IntWritable();

        public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
            int sum = 0;
            IntWritable val;
            for (Iterator i = values.iterator(); i.hasNext(); sum += val.get()) {
                val = (IntWritable) i.next();
            }
            this.result.set(sum);
            context.write(key, this.result);
        }
    }
}

這里面就涉及到了一些API,這個可以自己去網(wǎng)上查胜卤,這里不做過多介紹疆导。

接下來需要做的就是執(zhí)行這個程序,首先葛躏,將這個程序打包成jar澈段,然后上傳服務器

mvn clen install

在hdfs系統(tǒng)上準備好數(shù)據(jù),編輯 dream.txt 文件內(nèi)容如下

Hello bob

I am good

How are you

I am fine

Good good study

上傳dream.txt到hdfs系統(tǒng)

hadoop fs -mkdit /test
hadoop fs -put dream.txt /test/dream.txt

執(zhí)行MapReducer-1.0.jar程序

hadoop jar MapReducer-1.0.jar com.hand.sxy.WordCount

在控制臺和瀏覽器上觀察

image.png

瀏覽器打開:http://master:8088/cluster/apps

image.png

瀏覽器打開:http://master:50070/explorer.html#/output

程序結果即在hsfs中的 /output/part-r-00000文件中

hadoop fs -cat /output/part-r-00000

輸出的就是每個單詞出現(xiàn)的次數(shù)舰攒,這就是一個最簡單的MapReducer程序败富。

HA集群

hadoop的HA集群,即hadoop的高可用集群配置摩窃,為了解決hadoop中的NameNode單點故障問題兽叮。這個配置的時候比較繁瑣,有空再補上

安裝HIVE

HIVE是在MapReducer上的一層封裝偶芍,通過寫sql方式來實現(xiàn)MapReducer程序。什么意思德玫?就是說大部分情況下匪蟀,有了HIVE之后,不需要再開發(fā)MapReducer程序了宰僧,直接寫HQL即可材彪,大大節(jié)約了時間成本。HIVE非常強大,在創(chuàng)建hie表的時候段化,字段類型用的是java里面的數(shù)據(jù)類型嘁捷,連Map類型都可以用,很強大显熏。

下載安裝

http://mirror.bit.edu.cn/apache/hive/
http://mirrors.hust.edu.cn/apache/hive/
http://mirrors.shu.edu.cn/apache/hive/
http://mirrors.tuna.tsinghua.edu.cn/apache/hive/

安裝位置隨便安裝到那臺機器都都可以雄嚣,先解壓

tax -zxvf apache-hive-1.2.2-bin.tar.gz

6.2. 配置文件

添加一個hive-site.xml配置文件

<configuration>
  <property>
    <name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://centos81:3306/hive?
createDatabaseIfNotExist=true</value>
  </property>

  <property>
    <name>javax.jdo.option.ConnectionDriverName</name>
    <value>com.mysql.jdbc.Driver</value>
  </property>

  <property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>root</value>
  </property>

  <property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>root</value>
  </property>
</configuration>

這里其實就是配置hive元數(shù)據(jù)的存放位置,即hive中的數(shù)據(jù)庫名喘蟆、表名缓升、字段等西信息。其實不配置也沒關系蕴轨, hive默認內(nèi)置了一個其它 的數(shù)據(jù)庫港谊。

這里選擇的是mysql數(shù)據(jù)庫,所以還需要提供一個mysql驅(qū)動包橙弱,這里是:mysql-connector-java-5.1.46.jar

啟動

cd hive-1.2.2

bin/hive

如果你已經(jīng)安裝好了mysql歧寺,執(zhí)行這個命令之后,就會在mysql下創(chuàng)建一個hive數(shù)據(jù)庫棘脐。如圖:


之后斜筐,就可以用一些hive的語法了。

常見命令

和我們的sql非常類似

列出數(shù)據(jù)庫:show databases;

創(chuàng)建數(shù)據(jù)庫:create database 數(shù)據(jù)庫名;

使用數(shù)據(jù)庫:use 數(shù)據(jù)庫 名;

創(chuàng)建數(shù)據(jù)表:create table 表名 (xxx);

創(chuàng)建外部表:create external table 表名 (xxx);

創(chuàng)建分區(qū)表:create external table 表名 (xxx) partitioned by (day string);

配置分隔符:在建表語句后面加 row format delimited fields terminated by ',' ;

測試

在hive中新建數(shù)據(jù)庫和表荆残,并在hadoop中上傳文件奴艾,看看在hivez怎么通過sql查出來。

create database tsdb;
use tsdb;
create table t_test1(id int,name string,age int) row format delimited fields terminated by ',';

執(zhí)行以上命令之后内斯,觀察在hadoop中hdfs的目錄



image.png

可以看到蕴潦,生成了一個和數(shù)據(jù)庫名相同的文件夾子健无,點進去發(fā)現(xiàn)惋戏,也生成了一個和表名對應的目錄。

vi t_test1.txt

文件內(nèi)容如下:

1,xiaoyong,20
2,gaoxiao,40
3,liuxin,19

上傳這個文件到hdfs

hadoop fs -put t_test1.txt /user/hive/warehouse/tsdb.db/t_test1

在hive控制臺查詢

select * from t_test1;

[圖片上傳失敗...(image-83e835-1535979338058)]

結果已經(jīng)查出來了痴腌。

這本是一個MapReducer程序做的事情真朗,現(xiàn)在一個SQL就搞定了此疹。Hive中還有很多概念,這里就不做過多結算了遮婶。

安裝MySQL

這里安裝MySQL的目的就一個:保存HIVE中的元數(shù)據(jù)蝗碎。在安裝MySQL之前,先裝一個虛擬機旗扑,修改IP蹦骑,修改四臺機器的 /etc/host,這就當作是一臺專用數(shù)據(jù)庫服務器臀防。

更新yum源

下載mysql的yum源:

wget -P /home/lisonglin [http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm](http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm)

安裝mysql的yum源:

rpm -ivh mysql57-community-release-el7-11.noarch.rpm

安裝

執(zhí)行以下命令眠菇,然后一直按y就可以了

yum install mysql-community-server

啟動測試

啟動服務

systemctl start mysqld

通過mysql客戶但登錄mysql边败,默認是不需要密碼

mysql -uroot

設置密碼

set password = passeord(‘root’);

修改配置文件,這里只修改編碼集捎废,配置文件默認在 /etc/my.cnf

show variables lie ‘character%’;

vi /etc/my.cnf

[mysql]

default-character-set = utf8

[mysqld]

character_set_server = utf8

常用命令

常見的 啟動笑窜、停止、重啟等命令

啟動:systemctl start mysqld   

停止:# systemctl stop mysqld 

重啟:systemctl restart mysqld 

設置開機啟動:systemctl enable mysqld 

查看 MySQL Server 狀態(tài):systemctl status mysqld   

安裝Zookeeper

Zookeeper是一個基礎組件登疗,主要功能包括:

可以為客戶端管理少量數(shù)據(jù)排截,其中在zookeeeper中數(shù)據(jù)為鍵值格式。其中key類似于文件目錄結構谜叹,但不是目錄

/aa “valuea”

/aa/cc “valueb”

可以為客戶端監(jiān)聽指定數(shù)據(jù)節(jié)點得裝填匾寝,并在數(shù)據(jù)節(jié)點發(fā)生變化時通知客戶端。
應用場景:zookeeeper的應用場景可以非常廣泛荷腊,比如微服務架構中的服務注冊中心艳悔,用于服務上下線動態(tài)感知。zookeeper在hadoop體系中是為了高可用女仰,是為了解決DataNode的單點故障問題猜年;在Hbase中保存了Hbase各個ReginServer和master的信息。

下載安裝

生產(chǎn)環(huán)境一般是部署zookeeper集群疾忍,部署到奇數(shù)臺服務器乔外,一般3臺或者5臺。zookeeper有一個投票選舉機制一罩,所以有個leader 和 flower概念杨幼。

下載地址:http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.12/

解壓:tax -zxvf zookeeper-3.4.12.tar.gz

8.2. 配置文件

cd zookeeper-3.4.12/conf

cp zoo_sample.cfg zoo.cfg

vi zoo.cfg

我的配置文件內(nèi)容如下:

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/home/hadoop/cludata/zkdata
# the port at which the clients will connect
clientPort=2181
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.21=master:2888:3888
server.22=slave1:2888:3888
server.23=slave2:2888:3888

創(chuàng)建zk數(shù)據(jù)目錄

cd ~
mkdir -p cludata/zkdata

啟動

在三臺服務器下分別執(zhí)行以下命令

cd ~/zookeeper-3.4.12/

bin/zkServer.sh start

在啟動之后可以查看狀態(tài)

bin/zkServer.sh status


啟動腳本

為了方便啟動,提供一個啟動腳本

常見命令

進入客戶端

cd zookeeper-3.4.12

bin/zkCli.sh

//或者連接到其它服務器

bin/zkCli.sh -server slave1:2181

zookeeper 下提供了一些常見客戶端命令

創(chuàng)建節(jié)點:create /aa “value”

查看節(jié)點:ls /

查看數(shù)據(jù):get /aa

修改數(shù)據(jù):set /add “vakue2”

刪除節(jié)點:rmr /aa

監(jiān)聽數(shù)據(jù):get /aa watch

安裝HBASE

HBase是一個基于HDFS的NoSQL數(shù)據(jù)庫聂渊,可以提供數(shù)據(jù)的實時隨機讀寫差购,其中包括的概念有:HMaster、HRegionServer汉嗽、庫名欲逃、表名、行鍵饼暑、列族等稳析,其中HBase集群中的各個節(jié)點信息是維護在zookeeper中的。

下載安裝

下載地址:http://apache.claz.org/hbase/1.2.6.1/

tar -zxvf

HBase中包括兩個角色:HMaster弓叛、HRegionServer彰居。HMaster負責管理HRegionServer,數(shù)據(jù)讀寫交給HRegionServer撰筷。其中陈惰,HRegionServer應該和HDFS中的DataNode安裝在一起。

配置文件

主要修改三個配置文件:hbase-env.sh闭专、hbase-site.xml奴潘、regionservers

cd hbase-1.2.6.1/conf

修改hbase-env.sh

export JAVA_HOME=/home/hadoop/jdk1.8

//hbase自己有一套zookeeper管理機制,這里不使用自帶的影钉,而是使用我們配置的

export HBASE_MANAGES_ZK=false

修改hbase-site.xml

<configuration>
  <!-- 指定hbase在HDFS上存儲的路徑 -->
  <property>
    <name>hbase.rootdir</name>
    <value>hdfs://master:9000/hbase</value>
  </property>

  <!-- 指定hbase是分布式的 -->
  <property>
    <name>hbase.cluster.distributed</name>
    <value>true</value>
  </property>

  <!-- 指定zk的地址画髓,多個用“,”分割 -->
  <property>
    <name>hbase.zookeeper.quorum</name>
    <value>master:2181,slave1:2181,slave2:2181</value>
  </property>
</configuration>

修改regionservers,這里就是配置HRegionServer服務器的

slave1
slave2

然后將安裝包拷貝到slave1 和 slave2

scr -r hbase-1.2.6.1 hadoop@slave1:/home/hadoop
scr -r hbase-1.2.6.1 hadoop@slave2:/home/hadoop

啟動

啟動hbase的時候有個要求平委,需要各個服務器之間時間差不超過30s奈虾,所以在啟動之前需要先設置同步一下服務器時間,可以選擇時間服務器廉赔,這里就直接用命令了

date -s "2018-07-08 16:39:03"

//寫入bios肉微,防止重啟系統(tǒng)時間又變了

hwclock -w

啟動hdfs,不啟動yarn也沒關系蜡塌,在master服務器啟動

cd hadoop-2.7.6
sbin/start-dfs.sh

啟動zookeeper碉纳,進入三臺服務器啟動

cd zookeeper-3.4.12
bin/zkServer.sh start

啟動hbase

bin/start-hbase.sh

啟動之后,三臺服務器上的進程分別如下馏艾,可以看到hbase已經(jīng)啟動起來了




啟動成功之后劳曹,也可以在瀏覽器上觀察效果
http://master:16010

前面已經(jīng)說過,hbase相關的節(jié)點信息和zookeeper已經(jīng)關聯(lián)了琅摩,所以可以在zookeeper上查看hbase相關信息

cd zookeeper-3.4.12
bin/zkCli.sh

Hbase的文件存儲是基于HDFS的铁孵,所以也可以在hdfs上看到hbase相關的目錄
打開瀏覽器:http://master:50070/explorer.htm

命令行

Hbase提供了一些交互命令,但是這種情況我們用的不多一般是在程序中通過API來對hbase交互房资。

進入hbase命令行客戶端

cd hbase-1.2.6.1
bin/hbase shell

常用命令如下:


image.png

常見用法

創(chuàng)建表

create 表名, 列族名, 列族名 ……
create 't_user_info','base_info','extra_info'

插入數(shù)據(jù)

put 't_user_info','001','base_info:username','zhangsan'
put 't_user_info','001','base_info:age','18'

查詢數(shù)據(jù)

scan 't_user_info'
get 't_user_info','001'

刪除kv數(shù)據(jù)

delete 't_user_info','001','base_info:sex'
deleteall 't_user_info','001'

刪除表

先禁用蜕劝,然后刪除
disable 't_user_info'

drop 't_user_info'

API

創(chuàng)建一個連接

Connection conn = ConnectionFactory.createConnection(conf);

拿到一個DDL容器

Admin admin = conn.getAdmin();

用表管理器的API去操作表

admin.createTable(HTableDescriptor descriptor);

創(chuàng)建一個連接

Connection conn = ConnectionFactory.createConnection(conf);

安裝Flume

Flume用于數(shù)據(jù)采集。在實際開發(fā)中轰异,有各種各樣的數(shù)據(jù)來源岖沛,比如:kafka、mysql溉浙、hbase等等烫止,而我們的業(yè)務系統(tǒng),往往需要根據(jù)不用的數(shù)據(jù)來源開發(fā)不同的程序戳稽。Flume就相當一層殼馆蠕,并且里面提供了一些常用的實現(xiàn)類,有個核心概念就Agent惊奇,可以啟動Agent程序進行數(shù)據(jù)采集互躬,大大減少了我們的開發(fā)時間。

不過看網(wǎng)上說颂郎,F(xiàn)lume在嚴格場景是不推薦使用的吼渡,會有問題。所以簡單了解一下吧乓序。

下載安裝

下載地址

http://mirror.bit.edu.cn/apache/flume/1.8.0/apache-flume-1.8.0-bin.tar.gz http://mirrors.hust.edu.cn/apache/flume/1.8.0/apache-flume-1.8.0-bin.tar.gz http://mirrors.shu.edu.cn/apache/flume/1.8.0/apache-flume-1.8.0-bin.tar.gz http://mirrors.tuna.tsinghua.edu.cn/apache/flume/1.8.0/apache-flume-1.8.0-bin.tar.gz

解壓并拷貝到其它兩臺機器

tar -zxvf apache-flume-1.8.0-bin.tar.gz

scp -r flume-1.8.0 hadoop@slave1:/home/hadoop

scp -r flume-1.8.0 hadoop@slave2:/home/hadoop

配置文件

使用Flume主要就是配置了寺酪,需要編寫的配置內(nèi)容比較多坎背。 這里就不過多介紹了,有興趣的網(wǎng)上了解一下寄雀。

問題總結

DataNode無法啟動

多次執(zhí)行hadoop namenode -format命令得滤,slave 上的執(zhí)行這個命令之前,我已經(jīng)清空了三臺服務器下的一些目錄盒犹,并且停掉了所有進程

cd /home/hadoop/hadoop
rm -rf temp/*
rm -rf hdfs/name/* hdfs/data/*
cd hadoop-2.7.6
rm -rf logs/*
sbin/stop-all.sh

然后在master上執(zhí)行以下命令

sbin/ hadoop-daemon.sh start namenode
sbin/ hadoop-daemon.sh start datanode

執(zhí)行該命令后懂更,發(fā)現(xiàn)在 master節(jié)點上找到了 NameNode 和 DataNode 進行,但是在其它兩臺服務器上未找到 DataNode 進程急膀。

最后的解決方案:

分別在slave1 和 slave2 上執(zhí)行 以下命令

sbin/ hadoop-daemon.sh start datanode

這時候可以在 slave1 和 slave2 上找到 DataNode進程沮协。

同時,在瀏覽器上可以發(fā)現(xiàn)3個DataNode
http://192.168.88.21:50070/dfshealth.html#tab-datanode

可能應該在三臺服務器上把 hdfs目錄下的所有文件和文件夾都清空卓嫂,或者把整個hdfs目錄刪除慷暂。

同理,對于slave1 和slave2 上的沒有NodeManager進程情況晨雳,就手動在slave1和slave2上啟動

yarn-daemon.sh start nodemanager

http://192.168.88.21:8088/cluster/nodes

腳本啟動權限問題

執(zhí)行 sbin/start-dfs.fs 命令呜呐,通過ssh的方式啟動slave1和slave2節(jié)點,提示沒有/tmp目錄的權限悍募,但是很好奇都是hadoop用戶蘑辑,啟動本地的NameNode卻沒有權限問題。單絲坠宴,雖然提示權限問題洋魂,兩個DataNode卻都已經(jīng)啟動了。

為了去除這個警告喜鼓,嘗試是將 /tmp 目錄的權限賦給hadoop用戶副砍,分別在三臺機器上執(zhí)行以下命令

chown -R hadoop /tmp

再次重啟hadoop

sbin/stat-dfs.sh
sbin/stat-yarn.sh

發(fā)現(xiàn)警告已經(jīng)沒有了,同時兩臺DataNode已經(jīng)啟動成功庄岖。

這時候豁翎,三臺機器下分別啟動的進程有

**master**:NameNode、SecondaryNameNode隅忿、ResourceManager

**slave1**:DataNode心剥、NodeManager、

**slave2**:DataNode背桐、NodeManager优烧、

可以這樣理解:NameNode用于管理DataNode,而ResourceManager用于管理NodeManager链峭。

其實這個問題還有另外一種解決方案畦娄,就是修改 etc/hadoop/hadoop.env配置文件,里面有那么個選項可以修改。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末熙卡,一起剝皮案震驚了整個濱河市杖刷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驳癌,老刑警劉巖挺勿,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異喂柒,居然都是意外死亡,警方通過查閱死者的電腦和手機禾嫉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門灾杰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人熙参,你說我怎么就攤上這事艳吠。” “怎么了孽椰?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵昭娩,是天一觀的道長。 經(jīng)常有香客問我黍匾,道長栏渺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任锐涯,我火速辦了婚禮磕诊,結果婚禮上,老公的妹妹穿的比我還像新娘纹腌。我一直安慰自己霎终,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布升薯。 她就那樣靜靜地躺著莱褒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涎劈。 梳的紋絲不亂的頭發(fā)上广凸,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音蛛枚,去河邊找鬼炮障。 笑死,一個胖子當著我的面吹牛坤候,可吹牛的內(nèi)容都是我干的胁赢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼白筹,長吁一口氣:“原來是場噩夢啊……” “哼智末!你這毒婦竟也來了谅摄?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤系馆,失蹤者是張志新(化名)和其女友劉穎送漠,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體由蘑,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡闽寡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了尼酿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爷狈。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖裳擎,靈堂內(nèi)的尸體忽然破棺而出涎永,到底是詐尸還是另有隱情,我是刑警寧澤鹿响,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布羡微,位于F島的核電站,受9級特大地震影響惶我,放射性物質(zhì)發(fā)生泄漏妈倔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一绸贡、第九天 我趴在偏房一處隱蔽的房頂上張望启涯。 院中可真熱鬧,春花似錦恃轩、人聲如沸结洼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽松忍。三九已至,卻和暖如春筷厘,著一層夾襖步出監(jiān)牢的瞬間鸣峭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工酥艳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留摊溶,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓充石,卻偏偏與公主長得像莫换,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355