什么是Hadoop
Hadoop名字的由来
Hadoop的概念:
Hadoop能做什么?
搜索引擎
日志分析
数据挖掘
商业智能(Business Intelligence,简称:BI)
商业智能通常被理解为将企业中现有的数据(订单、库存、交易账目、客户和供应商等数据)转化为知识,帮助企业做出明智的业务经营决策的工具。从技术层面上讲,是数据仓库、数据挖掘等技术的综合运用。
Hadoop发展史
2003-2004年 Google发表了三篇论文
2006年2月Hadoop成为Apache的独立开源项目( Doug Cutting等人实现了GFS和MapReduce机制)。
2006年4月— 标准排序(10 GB每个节点)在188个节点上运行47.9个小时。
2008年4月— 赢得世界最快1TB数据排序在900个节点上用时209秒。
2008年— 淘宝开始投入研究基于Hadoop的系统–云梯。云梯总容量约9.3PB,共有1100台机器,每天处理18000道作业,扫描500TB数据。
2009年3月— Cloudera推出CDH(Cloudera’s Dsitribution Including Apache Hadoop)
2009年5月— Yahoo的团队使用Hadoop对1 TB的数据进行排序只花了62秒时间。
2009年7月— Hadoop Core项目更名为Hadoop Common;
2009年7月— MapReduce和Hadoop Distributed File System (HDFS)成为Hadoop项目的独立子项目。
2012年11月— Apache Hadoop 1.0 Available
2018年4月— Apache Hadoop 3.1 Available
搜索引擎时代
数据仓库时代
数据挖掘时代
机器学习时代 广义大数据
Hadoop是所有搜索引擎的共性问题的廉价解决方案
Hadoop Common: The common utilities that support the other Hadoop modules.(hadoop的核心组件)
Hadoop Distributed File System (HDFS™): A distributed file system that provides high-throughput access to application data.(分布式文件系统)
下面这张图是数据块多份复制存储的示意
Hadoop MapReduce: A YARN-based system for parallel processing of large data sets.
Hadoop YARN: A framework for job scheduling and cluster resource management.(资源调度系统)
分布式文件系统的设计思路:
HDFS的设计目标
http://archive.cloudera.com/cdh5/cdh/5/
下载java(JDK 1.7及以上)
Maven(3.3.9及以上)
hadoop 放到 /目录下
然后解压到 /app目录下
#cd /
#wget http://archive.cloudera.com/cdh5/cdh/5/hadoop-2.6.0-cdh5.7.0.tar.gz
#wget https://download.oracle.com/otn/java/jdk/8u271-b09/61ae65e088624f5aaa0b1d2d801acb16/jdk-8u271-linux-x64.tar.gz?AuthParam=1609064624_36802ed3834b595e16296e7570d706a3
#wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
#tar -zxvf 压缩包名字 -C /app/
#tar -zxvf jdk-8u271-linux-x64.tar.gz -C /app/
#tar -zxvf apache-maven-3.3.9-bin.tar.gz -C /app/
#tar -zxvf hadoop-2.6.0-cdh5.7.0.tar.gz -C /app/
配置环境变量
#hadoop-2.6.0-cdh5.7.0 jdk1.8.0_271
#vi ~/.bash_profile
export JAVA_HOME=/app/jdk1.8.0_271
export JRE_HOME=/app/jdk1.8.0_271/jre
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$PATH
export MAVEN_HOME=/app/apache-maven-3.3.9
export PATH=$MAVEN_HOME/bin:$PATH
export HADOOP_HOME=/app/hadoop-2.6.0-cdh5.7.0
export PATH=$HADOOP_HOME/bin:$PATH
#保存退出后
#source ~/.bash_profile
#vim /app/apache-maven-3.3.9/conf/settings.xml
<mirror>
<id>aliyunmavenid>
<mirrorOf>*mirrorOf>
<name>阿里云公共仓库name>
<url>https://maven.aliyun.com/repository/publicurl>
mirror>
进入到解压后的hadoop目录 修改配置文件
配置文件作用
修改hadoop-env.sh
cd /app/hadoop-2.6.0-cdh5.7.0/etc/hadoop
vi hadoop-env.sh
#找到下面内容添加java home
export JAVA_HOME=/app/jdk1.8.0_271
vi core-site.xml
<property>
<name>fs.default.name</name>
<value>hdfs://hadoop-master:8020</value>
</property>
vi hdfs-site.xml
<property>
<name>dfs.namenode.name.dir</name>
<value>/app/tmp/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/app/tmp/dfs/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
cp mapred-site.xml.template mapred-site.xml
vi mapred-site.xml
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
vi yarn-site.xml
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
vi /app/hadoop-2.6.0-cdh5.7.0/etc/hadoop/slaves
hadoop-master
来到hadoop的bin目录
cd /app/hadoop-2.6.0-cdh5.7.0/bin
./hadoop namenode -format (这个命令只运行一次)
启动hdfs 进入到 sbin
cd /app/hadoop-2.6.0-cdh5.7.0/sbin
./start-dfs.sh
启动时需要输入密码处理方式:
#原因 没有配置本地ssh 免密登录
#安装
#OpenSSH是Secure Shell的一个开源实现。CentOS的软件库里面已经有了OpenSSH的服务器包(openssh-#server)和客户端包(openssh-clients),用yum install可以直接安装。
yum install openssh-server
#生成秘钥文件
ssh-keygen -t rsa
#实现本地登录免密码登录,地的公钥导入授权文件就可以
cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
启动HDFS
[root@hadoop-master sbin]# cd /app/hadoop-2.6.0-cdh5.7.0/sbin/
[root@hadoop-master sbin]# ./start-dfs.sh
20/12/27 06:16:03 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Starting namenodes on [hadoop-master]
hadoop-master: namenode running as process 3699. Stop it first.
hadoop-master: datanode running as process 2713. Stop it first.
Starting secondary namenodes [0.0.0.0]
0.0.0.0: secondarynamenode running as process 3938. Stop it first.
20/12/27 06:16:33 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
[root@hadoop-master sbin]# jps
3938 SecondaryNameNode
3699 NameNode
4887 Jps
2713 DataNode
通过可视化界面查看HDFS的运行情况
调用文件系统(FS)Shell命令应使用 bin/hadoop fs 的形式
使用方法:hadoop fs -ls
如果是文件,则按照如下格式返回文件信息:
文件名 <副本数> 文件大小 修改日期 修改时间 权限 用户ID 组ID
如果是目录,则返回它直接子文件的一个列表,就像在Unix中一样。目录返回列表的信息如下:
目录名
使用方法:hadoop fs -text
将源文件输出为文本格式。允许的格式是zip和TextRecordInputStream。
mv
使用方法:hadoop fs -mv URI [URI …]
将文件从源路径移动到目标路径。这个命令允许有多个源路径,此时目标路径必须是一个目录。不允许在不同的文件系统间移动文件。
示例:
返回值:
成功返回0,失败返回-1。
put
使用方法:hadoop fs -put …
从本地文件系统中复制单个或多个源路径到目标文件系统。也支持从标准输入中读取输入写入目标文件系统。
返回值:
成功返回0,失败返回-1。
使用方法:hadoop fs -rm URI [URI …]
删除指定的文件。只删除非空目录和文件。请参考rmr命令了解递归删除。
示例:
返回值:
成功返回0,失败返回-1。
http://hadoop.apache.org/docs/r1.0.4/cn/hdfs_shell.html
在centos 中创建 test.txt
touch test.txt
在centos中为test.txt 添加文本内容
vi test.txt
在HDFS中创建 hadoop001/test 文件夹
hadoop fs -mkdir -p /hadoop001/test
把text.txt文件上传到HDFS中
hadoop fs -put test.txt /hadoop001/test/
查看hdfs中 hadoop001/test/test.txt 文件内容
hadoop fs -cat /hadoop001/test/test.txt
将hdfs中 hadoop001/test/test.txt文件下载到centos
hadoop fs -get /hadoop001/test/test.txt test.txt
删除HDFS中 hadoop001/test/
hadoop fs -rm -r /hadoop001
通用资源管理系统
服务器集群资源调度管理和MapReduce执行过程耦合在一起带来的问题
不同计算框架可以共享同一个HDFS集群上的数据,享受整体的资源调度
1,Client提交作业请求
2,ResourceManager 进程和 NodeManager 进程通信,根据集群资源,为用户程序分配第一个Container(容器),并将 ApplicationMaster 分发到这个容器上面
3,在启动的Container中创建ApplicationMaster
4,ApplicationMaster启动后向ResourceManager注册进程,申请资源
5,ApplicationMaster申请到资源后,向对应的NodeManager申请启动Container,将要执行的程序分发到NodeManager上
6,Container启动后,执行对应的任务
7,Tast执行完毕之后,向ApplicationMaster返回结果
8,ApplicationMaster向ResourceManager 请求kill进程
1)修改mapred-site.xml configuration中添加
#cd /app/hadoop-2.6.0-cdh5.7.0/etc/hadoop
#vi /mapred-site.xml
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
2)修改 yarn-site.xml configuration中添加
#vi yarn-site.xml
<property>
<name>yarn.nodemanager.aux-servicesname>
<value>mapreduce_shufflevalue>
property>
#cd /app/hadoop-2.6.0-cdh5.7.0/sbin
./start-yarn.sh
4)验证
#jps
ResourceManager
NodeManager
http://192.168.31.137:8088/
5)停止YARN相关的进程
#cd /app/hadoop-2.6.0-cdh5.7.0/sbin
./stop-yarn.sh
MapReduce分而治之的思想
MapReduce编程分Map和Reduce阶段
MapReduce编程执行步骤
编程模型
Mapper
#map.py
import sys
#输入为标准输入stdin
for line in sys.stdin:
#删除开头和结尾的空行
line = line.strip()
#以默认空格分隔单词到words列表
words = line.split()
for word in words:
#输出所有单词,格式为“单词 1”以便作为Reduce的输入
print("%s %s"%(word,1))
Reducer
#red.py
import sys
current_word = None
current_count = 0
word = None
#获取标准输入,即mapper.py的标准输出
for line in sys.stdin:
#删除开头和结尾的空行
line = line.strip()
#解析mapper.py输出作为程序的输入,以tab作为分隔符
word,count = line.split()
#转换count从字符型到整型
try:
count = int(count)
except ValueError:
#count非数字时,忽略此行
continue
#要求mapper.py的输出做排序(sort)操作,以便对连续的word做判断
if current_word == word:
current_count += count
else :
#出现了一个新词
#输出当前word统计结果到标准输出
if current_word :
print('%s\t%s' % (current_word,current_count))
#开始对新词的统计
current_count = count
current_word = word
#输出最后一个word统计
if current_word == word:
print("%s\t%s"% (current_word,current_count))
[root@hadoop-master temp_test]# pwd
/temp_test
[root@hadoop-master temp_test]# ls
map.py red.py test.txt
[root@hadoop-master temp_test]# cat test.txt
hadoop test
hello word count
hadoop streaming
spark spark sql
[root@hadoop-master temp_test]# cat test.txt|python3 map.py|sort|python3 red.py
count 1
hadoop 2
hello 1
spark 2
sql 1
streaming 1
test 1
word 1
[root@hadoop-master temp_test]# hadoop fs -mkdir -p /temp_test/output
[root@hadoop-master temp_test]# hadoop fs -put test.txt /temp_test/
注:hadoop-streaming会主动将map的输出数据进行字典排序
通过Hadoop Streaming 提交作业到Hadoop集群
#vi straming.sh
STREAM_JAR_PATH="/app/hadoop-2.6.0-cdh5.7.0/share/hadoop/tools/lib/hadoop-streaming-2.6.0-cdh5.7.0.jar"
# hadoop streaming jar包所在位置
INPUT_FILE_PATH_1="/temp_test/test.txt" #要进行词频统计的文档在hdfs中的路径
OUTPUT_PATH="/temp_test/output" #MR作业后结果的存放路径
hadoop fs -rm -r -skipTrash $OUTPUT_PATH # 输出路径如果之前存在 先删掉否则会报错
hadoop jar $STREAM_JAR_PATH \
-input $INPUT_FILE_PATH_1 \ # 指定输入文件位置
-output $OUTPUT_PATH \ #指定输出结果位置
-mapper "/usr/local/python38/bin/python3 map.py" \ #指定mapper执行的程序
-reducer "/usr/local/python38/bin/python3 red.py" \ # 指定reduce阶段执行的程序
-file ./map.py \ # 通过-file 把python源文件分发到集群的每一台机器上
-file ./red.py
[root@hadoop-master temp_test]# cat straming.sh
STREAM_JAR_PATH="/app/hadoop-2.6.0-cdh5.7.0/share/hadoop/tools/lib/hadoop-streaming-2.6.0-cdh5.7.0.jar"
# hadoop streaming jar包所在位置
INPUT_FILE_PATH_1="/temp_test/test.txt" #要进行词频统计的文档在hdfs中的路径
OUTPUT_PATH="/temp_test/output" #MR作业后结果的存放路径
hadoop fs -rm -r -skipTrash $OUTPUT_PATH # 输出路径如果之前存在 先删掉否则会报错
hadoop jar $STREAM_JAR_PATH -input $INPUT_FILE_PATH_1 -output $OUTPUT_PATH -mapper "/usr/local/python38/bin/python3 map.py" -reducer "/usr/local/python38/bin/python3 red.py" -file ./map.py -file ./red.py
[root@hadoop-master temp_test]#chmod +x straming.sh
[root@hadoop-master temp_test]#./straming.sh
到Hadoop集群查看运行结果
[root@hadoop-master temp_test]# hadoop fs -ls /temp_test/output
Found 2 items
-rw-r--r-- 1 root supergroup 0 2020-12-27 09:22 /temp_test/output/_SUCCESS
-rw-r--r-- 1 root supergroup 65 2020-12-27 09:22 /temp_test/output/part-00000
[root@hadoop-master temp_test]# hadoop fs -cat /temp_test/output/part-00000
count 1
hadoop 2
hello 1
spark 2
sql 1
streaming 1
test 1
word 1
mrjob 简介
mrjob 安装
mrjob实现WordCount
from mrjob.job import MRJob
class MRWordFrequencyCount(MRJob):
def mapper(self, _, line):
yield "chars", len(line)
yield "words", len(line.split())
yield "lines", 1
def reducer(self, key, values):
yield key, sum(values)
if __name__ == '__main__':
MRWordFrequencyCount.run()
运行WordCount代码
打开命令行, 找到一篇文本文档, 敲如下命令:
python mr_word_count.py my_file.txt
1、内嵌(-r inline)方式
特点是调试方便,启动单一进程模拟任务执行状态和结果,默认(-r inline)可以省略,输出文件使用 > output-file 或-o output-file,比如下面两种运行方式是等价的
python word_count.py -r inline input.txt > output.txt
python word_count.py input.txt > output.txt
2、本地(-r local)方式
用于本地模拟Hadoop调试,与内嵌(inline)方式的区别是启动了多进程执行每一个任务。如:
python word_count.py -r local input.txt > output1.txt
3、Hadoop(-r hadoop)方式
用于hadoop环境,支持Hadoop运行调度控制参数,如:
1)指定Hadoop任务调度优先级(VERY_HIGH|HIGH),如:–jobconf mapreduce.job.priority=VERY_HIGH。
2)Map及Reduce任务个数限制,如:–jobconf mapreduce.map.tasks=2 --jobconf mapreduce.reduce.tasks=5
python word_count.py -r hadoop hdfs:///test.txt -o hdfs:///output --python-bin /root/Envs/ai/bin/python
统计数据中出现次数最多的前n个数据
import sys
from mrjob.job import MRJob,MRStep
import heapq
class TopNWords(MRJob):
def mapper(self, _, line):
if line.strip() != "":
for word in line.strip().split():
yield word,1
#介于mapper和reducer之间,用于临时的将mapper输出的数据进行统计
def combiner(self, word, counts):
yield word,sum(counts)
def reducer_sum(self, word, counts):
yield None,(sum(counts),word)
#利用heapq将数据进行排序,将最大的2个取出
def top_n_reducer(self,_,word_cnts):
for cnt,word in heapq.nlargest(2,word_cnts):
yield word,cnt
#实现steps方法用于指定自定义的mapper,comnbiner和reducer方法
def steps(self):
return [
MRStep(mapper=self.mapper,
combiner=self.combiner,
reducer=self.reducer_sum),
MRStep(reducer=self.top_n_reducer)
]
def main():
TopNWords.run()
if __name__=='__main__':
main()
需求描述
uid uname
01 user1
02 user2
03 user3
uid orderid order_price
01 01 80
01 02 90
02 03 82
02 04 95
mrjob 实现
实现对两个数据表进行join操作,显示效果为每个用户的所有订单信息
"01:user1" "01:80,02:90"
"02:user2" "03:82,04:95"
from mrjob.job import MRJob
import os
import sys
class UserOrderJoin(MRJob):
SORT_VALUES = True
# 二次排序参数:http://mrjob.readthedocs.io/en/latest/job.html
def mapper(self, _, line):
fields = line.strip().split('\t')
if len(fields) == 2:
# user data
source = 'A'
user_id = fields[0]
user_name = fields[1]
yield user_id,[source,user_name] # 01 [A,user1]
elif len(fields) == 3:
# order data
source ='B'
user_id = fields[0]
order_id = fields[1]
price = fields[2]
yield user_id,[source,order_id,price] #01 ['B',01,80]['B',02,90]
else :
pass
def reducer(self,user_id,values):
'''
每个用户的订单列表
"01:user1" "01:80,02:90"
"02:user2" "03:82,04:95"
:param user_id:
:param values:[A,user1] ['B',01,80]
:return:
'''
values = [v for v in values]
if len(values)>1 :
user_name = values[0][1]
order_info = [':'.join([v[1],v[2]]) for v in values[1:]] #[01:80,02:90]
yield ':'.join([user_id,user_name]),','.join(order_info)
def main():
UserOrderJoin.run()
if __name__ == '__main__':
main()
实现对两个数据表进行join操作,显示效果为每个用户所下订单的订单总量和累计消费金额
"01:user1" [2, 170]
"02:user2" [2, 177]
from mrjob.job import MRJob
import os
import sys
class UserOrderJoin(MRJob):
# 二次排序参数:http://mrjob.readthedocs.io/en/latest/job.html
SORT_VALUES = True
def mapper(self, _, line):
fields = line.strip().split('\t')
if len(fields) == 2:
# user data
source = 'A'
user_id = fields[0]
user_name = fields[1]
yield user_id,[source,user_name]
elif len(fields) == 3:
# order data
source ='B'
user_id = fields[0]
order_id = fields[1]
price = fields[2]
yield user_id,[source,order_id,price]
else :
pass
def reducer(self,user_id,values):
'''
统计每个用户的订单数量和累计消费金额
:param user_id:
:param values:
:return:
'''
values = [v for v in values]
user_name = None
order_cnt = 0
order_sum = 0
if len(values)>1:
for v in values:
if len(v) == 2 :
user_name = v[1]
elif len(v) == 3:
order_cnt += 1
order_sum += int(v[2])
yield ":".join([user_id,user_name]),(order_cnt,order_sum)
def main():
UserOrderJoin().run()
if __name__ == '__main__':
main()
单机程序计算流程
输入数据—>读取数据—>处理数据—>写入数据—>输出数据
Hadoop计算流程
input data:输入数据
InputFormat:对数据进行切分,格式化处理
map:将前面切分的数据做map处理(将数据进行分类,输出(k,v)键值对数据)
shuffle&sort:将相同的数据放在一起,并对数据进行排序处理
reduce:将map输出的数据进行hash计算,对每个map数据进行统计计算
OutputFormat:格式化输出数据
map:将数据进行处理
buffer in memory:达到80%数据时,将数据锁在内存上,将这部分输出到磁盘上
partitions:在磁盘上有很多"小的数据",将这些数据进行归并排序。
merge on disk:将所有的"小的数据"进行合并。
reduce:不同的reduce任务,会从map中对应的任务中copy数据
在reduce中同样要进行merge操作
MapReduce2.X架构
狭义的Hadoop VS 广义的Hadoop
Hive:数据仓库
R:数据分析
Mahout:机器学习库
pig:脚本语言,跟Hive类似
Oozie:工作流引擎,管理作业执行顺序
Zookeeper:用户无感知,主节点挂掉选择从节点作为主的
Flume:日志收集框架
Sqoop:数据交换框架,例如:关系型数据库与HDFS之间的数据交换
Hbase : 海量数据中的查询,相当于分布式文件系统中的数据库
Spark: 分布式的计算框架基于内存
Kafka: 消息队列
Storm: 分布式的流式计算框架 python操作storm
Flink: 分布式的流式计算框架
Hadoop生态系统的特点
开源、社区活跃
囊括了大数据处理的方方面面
成熟的生态圈
HDFS读写流程
客户端向NameNode发出写文件请求。
检查是否已存在文件、检查权限。若通过检查,直接先将操作写入EditLog,并返回输出流对象。
(注:WAL,write ahead log,先写Log,再写内存,因为EditLog记录的是最新的HDFS客户端执行所有的写操作。如果后续真实写操作失败了,由于在真实写操作之前,操作就被写入EditLog中了,故EditLog中仍会有记录,我们不用担心后续client读不到相应的数据块,因为在第5步中DataNode收到块后会有一返回确认信息,若没写成功,发送端没收到确认信息,会一直重试,直到成功)
client端按128MB的块切分文件。
client将NameNode返回的分配的可写的DataNode列表和Data数据一同发送给最近的第一个DataNode节点,此后client端和NameNode分配的多个DataNode构成pipeline管道,client端向输出流对象中写数据。client每向第一个DataNode写入一个packet,这个packet便会直接在pipeline里传给第二个、第三个…DataNode。
(注:并不是写好一个块或一整个文件后才向后分发)
每个DataNode写完一个块后,会返回确认信息。
(注:并不是每写完一个packet后就返回确认信息,个人觉得因为packet中的每个chunk都携带校验信息,没必要每写一个就汇报一下,这样效率太慢。正确的做法是写完一个block块后,对校验信息进行汇总分析,就能得出是否有块写错的情况发生)
写完数据,关闭输输出流。
发送完成信号给NameNode。
(注:发送完成信号的时机取决于集群是强一致性还是最终一致性,强一致性则需要所有DataNode写完后才向NameNode汇报。最终一致性则其中任意一个DataNode写完后就能单独向NameNode汇报,HDFS一般情况下都是强调强一致性)
HDFS如何实现高可用(HA)
Apache Hadoop
CDH: Cloudera Distributed Hadoop
HDP: Hortonworks Data Platform
数据采集
数据处理
数据输出与展示
任务调度系统
通过数据分析指标监控企业运营状态, 及时调整运营和产品策略,是大数据技术的关键价值之一
大数据平台(互联网企业)运行的绝大多数大数据计算都是关于数据分析的
运营数据是公司管理的基础
运营数据的获取需要大数据平台的支持
运营常用数据指标
新增用户数 UG user growth 用户增长
用户留存率
活跃用户数
PV Page View
GMV
转化率
转化率 = 有购买行为的用户数 / 总访问用户数
背景: 某电商网站, 垂直领域领头羊, 各项指标相对稳定
运营人员发现从 8 月 15 日开始,网站的订单量连续四天明显下跌
8 月 18 号早晨发现 8 月 17 号的订单量没有恢复正常,运营人员开始尝试寻找原因
没有找到原因, 将问题交给数据分析团队
数据分析师分析可能性
转化过程:
订单活跃转化率 = 日订单量 / 打开用户数
搜索打开转化率 = 搜索用户数 / 打开用户数
有明显降幅的是咨询详情转化率
Hadoop企业应用案例之消费大数据
亚马逊提前发货系统
Hadoop企业案例之商业零售大数据
智能推荐