Hadoop 介绍 使用

其他

luigi 任务调度框架教程

Hadoop、Hive、Spark 之间关系

【Hadoop】三句话告诉你 mapreduce 中MAP进程的数量怎么控制?

hive修改 表/分区语句

 

五分钟零基础搞懂Hadoop

「大数据」,想必大家经常听到这个被炒得很热的话题。随之而来的是各种看似高大上的专业术语,比如「扩展性」、「可靠性」、「容错性」,好像真的很高深,要积累多年经验才能学习。

 

但另一方面,很多同学都刚刚进入互联网这个行业,对分布式计算还没有很多了解,那是不是就要花很多力气才能搞懂「大数据」呢?不必担心,包子老师在这里用浅显易懂深入浅出的语言,帮助没有基础的同学快速的入手「大数据」,让每位同学都能迅速学会最前沿的技术。今天,我们先学习当前使用最广泛的大数据处理框架 Hadoop.

 

Hadoop,你是怎么来的?

 

今天的社会产生越来越多的数据,比如:你登录Facebook以后点击了哪些好友,你在Amazon上浏览了哪些产品,你在linkedin上浏览了哪些公司,甚至到从石油矿井里的钻头收集了哪些地质信息。

 

我们还发现,通过分析这些数据总结规律,我们可以让Facebook和Amazon显示让用户更感兴趣的广告,公司HR会更准确找到合适的求职者,石油公司也能用更低的成本开采更多的石油。

 

那找个软工写算法不就行了吗?

 

确实,这些决策都是通过算法找到规律的。可问题是现在的数据量太大了,一台机器要完成一个问题要算好久好久。

 

那用多台机器处理不就行了吗?

 

确实,Hadoop以及其他任何大数据框架都是多台机器共同处理的。可问题是,这些算法都要完成一个特定的问题,给出一个答案,多台机器不能自己算自己的,他们要有不同的分工,联合起来共同算完这个问题。这里就是Hadoop等框架的特长。

 

我们举个例子吧:

 

Google是大家常用的搜索引擎,作为业务的重要特征,它自然想知道大家对哪些关键字感兴趣,比如以天为单位,收集所有人搜过的关键字,统计其出现的次数。

 

这听起来像个哈希表就能干的问题对吧?可是,每天那么多人使用Google,它不可能把这些关键字都放在内存里,而且Google也是用很多服务器为大家完成搜索的,所以一天里所有搜过的关键字,都以文件的形式存在多台机器上。我们就叫这些机器1, 2, 3......n.

 

比如在机器1上存储了一个文件,内容是所有搜过的关键字:Deer, Bear, River …...

 

图1

 

既然Log文件存放在多台机器中,那如何计算关键字出现的总次数呢?

 

一种直观的算法,就是先让每台机器统计本机上每个关键字的搜索次数,写段算法统计一个文件里的关键字很简单。比如机器1的处理结果为:

 

  • Deer 150000

  • River 110000

  • Car 100000

(参见图1的mapping)

 

注意到这里,每台机器知道的是本机上关键字的搜索次数,而我们关心的是所有机器上的关键字的搜索总次数。

 

那下一步再找一组机器,不妨称其为:A, B, C, D......

 

每台机器只统计一部分关键字出现在所有机器上的总次数,比如:

  • 让机器A统计 在机器1, 2, 3.......n上“Bear”出现的总次数;

  • 让机器B统计,在机器1, 2, 3.......n上“Car”出现的总次数;

  • 让机器C统计,在机器1, 2, 3.......n上“Deer”出现的总次数;

  • 让机器D统计,在机器1, 2, 3......n上“River”出现的总次数;

(参见图1的reducing)

 

这样,当A, B, C, D......完成自己的任务以后,我们就知道每个关键字在过去一天出现的次数了。

 

所以每台机器不但要计算自己的任务,还要和其他机器「合作」,在我们刚才的例子里就是机器A, B, C, D......要从机器1, 2, 3, 4......那里知道关键字的出现次数,而且,A, B, C, D.....还要沟通好,分别统计不同的关键字,即不能两台机器都统计同一个关键字,也不能有的关键字没有机器统计。

 

好吧,大数据计算真复杂,那我们什么时候说说Hadoop?

 

其实,如果你明白了刚才的例子,你就明白Hadoop了!

 

啊?真的么?

 

是的,我们刚才计算搜索引擎关键字出现次数的例子,就是一个使用Hadoop的经典案例。像我们刚才说的,大数据计算非常复杂,各个机器之间要协调工作。但是,当总结常用的大数据算法后,我们发现他们有一定的共同点(稍后介绍),很多算法都要做一些类似的工作。既然有共同点,我们就没有必要重造轮子。这些类似的工作可以做成Framework,以后再开发类似大数据分析软件可以重用这些Framework的功能。Hadoop就是这样一个Framework,它来源于Google一篇关于MapReduce的Paper.

 

那Hadoop总结了算法的哪些共同点呢?

 

那篇MapReduce Paper的作者发现,很多计算,就比如我们刚才的例子,都可以拆分成Map, Shuffle, Reduce三个阶段:

 

  • Map阶段中,每台机器先处理本机上的数据,像图1中各个机器计算本机的文件中关键字的个数。

  • 各个机器处理完自己的数据后,我们再把他们的结果汇总,这就是Shuffle阶段,像刚才的例子,机器A, B, C, D......从1-n所有机器上取出Map的结果,并按关键字组合。

  • 最后,进行最后一步处理,这就是Reduce,我们刚才的例子中就是对每一个搜索关键字统计出现总次数。

 

这几步我们就称为MapReduce Model.

图2

为了完成MapReduce Model的计算,实际开发的软件需要一些辅助的功能。想像一下,起始时的一组机器上面存储了要处理的数据,但是Map, Shuffle, Reduce阶段的Function在哪儿呢?所以我们需要把Mapper Function, Reducer Function (Java code或者其他语言的code) 安装在机器 1-n 和A-Z上,并且执行。而且在Map阶段以后,计算结果保存在本机上,没办法Shuffle到Reduce的机器上。所以,也需要有软件按照Shuffle算法,把Mapper Function的结果搬运到Reduce阶段的机器上。

 

运行整个Hadoop Job的流程中,很多工作对于所有算法都是需要的,不同的算法只是Mapper Function和Reducer Function. 换句话说,Hadoop实现了通用的功能,开发人员只需要告诉Hadoop需要执行的Mapper, Reducer Function,就可以完成想要的计算,而不需要开发所有步骤。

 

HDFS基本命令的使用

hadoop HDFS常用文件操作命令

hdfs文件的相关操作主要使用hadoop fs、hadoop dfs、hdfs dfs 命令,以下对最常用的相关命令进行简要说明。

Hadoop fs:使用面最广,可以操作任何文件系统。

hadoop dfs与hdfs dfs:只能操作HDFS文件系统相关(包括与Local FS间的操作),前者已经Deprecated,一般使用后者。

hadoop fs 显示可用命令
hadoop fs -ls  显示当前目录结构,-ls -R 递归显示目录结构
hadoop fs -mkdir  创建目录
hadoop fs -rm   删除文件,-rm -R 递归删除目录和文件
hadoop fs -put  [localsrc] [dst]  从本地加载文件到HDFS
hadoop fs -get  [dst] [localsrc]  从HDFS导出文件到本地
hadoop fs - copyFromLocal [localsrc] [dst]  从本地加载文件到HDFS,与put一致
hadoop fs -copyToLocal [dst] [localsrc]  从HDFS导出文件到本地,与get一致
hadoop fs -test -e  检测目录和文件是否存在,存在返回值$?为0,不存在返回1
hadoop fs -text  查看文件内容
hadoop fs -du  统计目录下各文件大小,单位字节。-du -s 汇总目录下文件大小,-du -h 显示单位
hadoop fs -tail  显示文件末尾
hadoop fs -cp [src] [dst] 从源目录复制文件到目标目录
hadoop fs -mv [src] [dst] 从源目录移动文件到目标目录

查看部分数据:

hadoop fs -cat /your/file | head
hadoop fs -tail /your/file

让python代码在hadoop上运行

使用Python编写MapRecuce代码的技巧就在于我们使用了Hadoop streaming来帮助我们在map和reduce之间传递数据通过stdin和stdout,我们仅仅使用Python的sys.stdin来输入数据,使用Python的sys.stdout来输出数据,其他的streaming都会帮我们做好。别不信这一点!

首先创建map和reduce处理程序,用python实现。
mapper.py:

#!/usr/bin/env python

import sys

# input comes from STDIN (standard input)
for line in sys.stdin:
    # remove leading and trailing whitespace
    line = line.strip()
    # split the line into words
    words = line.split()
    # increase counters
    for word in words:
        # write the results to STDOUT (standard output);
        # what we output here will be the input for the
        # Reduce step, i.e. the input for reducer.py
        #
        # tab-delimited; the trivial word count is 1
        print '%s\t%s' % (word, 1)

recucer.py

#!/usr/bin/env python

from operator import itemgetter
import sys

current_word = None
current_count = 0
word = None

# input comes from STDIN
for line in sys.stdin:
    # remove leading and trailing whitespace
    line = line.strip()

    # parse the input we got from mapper.py
    word, count = line.split('\t', 1)

    # convert count (currently a string) to int
    try:
        count = int(count)
    except ValueError:
        # count was not a number, so silently
        # ignore/discard this line
        continue

    # this IF-switch only works because Hadoop sorts map output
    # by key (here: word) before it is passed to the reducer
    if current_word == word:
        current_count += count
    else:
        if current_word:
            # write result to STDOUT
            print '%s\t%s' % (current_word, current_count)
        current_count = count
        current_word = word

# do not forget to output the last word if needed!
if current_word == word:
    print '%s\t%s' % (current_word, current_count)

保存,比如我保存在本地的home/hadoop文件夹下面,并且要给这两个文件可执行权限
不用急着在hadoop上验证,可以先在本地验证map和reduce代码的正确性:

# very basic test
hduser@ubuntu:~$ echo "foo foo quux labs foo bar quux" | /home/hduser/mapper.py
foo     1
foo     1
quux    1
labs    1
foo     1
bar     1
quux    1

hduser@ubuntu:~$ echo "foo foo quux labs foo bar quux" | /home/hduser/mapper.py | sort -k1,1 | /home/hduser/reducer.py
bar     1
foo     3
labs    1
quux    2

# using one of the ebooks as example input
# (see below on where to get the ebooks)
hduser@ubuntu:~$ cat /tmp/gutenberg/20417-8.txt | /home/hduser/mapper.py
 The     1
 Project 1
 Gutenberg       1
 EBook   1
 of      1
 [...]
 (you get the idea)

如果本地验证通过,说明map和reduce的处理逻辑没有问题。然后可以下载三个文本文档作为输入源:
The Outline of Science, Vol. 1 (of 4) by J. Arthur Thomson
The Notebooks of Leonardo Da Vinci
Ulysses by James Joyce
然后把这三个文本上传到hdfs文件系统上:
bin/hdfs dfs -copyFromLocal /home/hadoop/gutenberg /user/hadoop/gutenberg
可以用bin/hdfs dfs -ls /user/hadoop/gutenberg来检测是否上传成功:

[hadoop@localhost hadoop-2.7.4]$ bin/hdfs dfs -ls /user/hadoop/gutenberg
Found 3 items
-rw-r--r--   1 hadoop supergroup      21293 2017-09-04 11:41 /user/hadoop/gutenberg/20417
-rw-r--r--   1 hadoop supergroup      23403 2017-09-04 11:41 /user/hadoop/gutenberg/4300
-rw-r--r--   1 hadoop supergroup      22178 2017-09-04 11:41 /user/hadoop/gutenberg/5000
[hadoop@localhost hadoop-2.7.4]$ 

然后要找到自己本地环境中安装hadoop中的stream jar包,我本地的stream包是

/home/hadoop/hadoop-2.7.4/share/hadoop/tools/lib/hadoop-streaming-2.7.4.jar

然后用此streaming的jar文件来运行就可以:

[hadoop@localhost hadoop-2.7.4]$ bin/hadoop jar /home/hadoop/hadoop-2.7.4/share/hadoop/tools/lib/hadoop-streaming-2.7.4.jar -file /home/hadoop/mapper.py    -mapper /home/hadoop/mapper.py -file /home/hadoop/reducer.py   -reducer /home/hadoop/reducer.py -input /user/test/gutenberg/* -output /user/test/gutenberg-output

或者:

[hadoop@localhost hadoop-2.7.4]$ bin/hadoop jar /home/hadoop/hadoop-2.7.4/share/hadoop/tools/lib/hadoop-streaming-2.7.4.jar   -mapper /home/hadoop/mapper.py  -reducer /home/hadoop/reducer.py -input /user/test/gutenberg/* -output /user/test/gutenberg-output

可以查看运行结果:

[hadoop@localhost hadoop-2.7.4]$ bin/hadoop jar /home/hadoop/hadoop-2.7.4/share/hadoop/tools/lib/hadoop-streaming-2.7.4.jar  -mapper /home/hadoop/mapper.py  -reducer /home/hadoop/reducer.py -input /user/test/gutenberg/* -output /user/test/gutenberg-output3
packageJobJar: [/tmp/hadoop-unjar2137675126277149757/] [] /tmp/streamjob3391053950303419829.jar tmpDir=null
17/09/04 14:33:18 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0:8032
17/09/04 14:33:18 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0:8032
17/09/04 14:33:19 INFO mapred.FileInputFormat: Total input paths to process : 3
17/09/04 14:33:19 INFO mapreduce.JobSubmitter: number of splits:3
17/09/04 14:33:19 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1504425057280_0005
17/09/04 14:33:20 INFO impl.YarnClientImpl: Submitted application application_1504425057280_0005
17/09/04 14:33:20 INFO mapreduce.Job: The url to track the job: http://localhost:8088/proxy/application_1504425057280_0005/
17/09/04 14:33:20 INFO mapreduce.Job: Running job: job_1504425057280_0005
17/09/04 14:33:31 INFO mapreduce.Job: Job job_1504425057280_0005 running in uber mode : false
17/09/04 14:33:31 INFO mapreduce.Job:  map 0% reduce 0%
17/09/04 14:33:51 INFO mapreduce.Job:  map 100% reduce 0%
17/09/04 14:34:00 INFO mapreduce.Job:  map 100% reduce 100%
17/09/04 14:34:00 INFO mapreduce.Job: Job job_1504425057280_0005 completed successfully
17/09/04 14:34:00 INFO mapreduce.Job: Counters: 49
    File System Counters
        FILE: Number of bytes read=86853
        FILE: Number of bytes written=748071
        FILE: Number of read operations=0
        FILE: Number of large read operations=0
        FILE: Number of write operations=0
        HDFS: Number of bytes read=67169
        HDFS: Number of bytes written=24946
        HDFS: Number of read operations=12
        HDFS: Number of large read operations=0
        HDFS: Number of write operations=2
    Job Counters 
        Launched map tasks=3
        Launched reduce tasks=1
        Data-local map tasks=3
        Total time spent by all maps in occupied slots (ms)=52498
        Total time spent by all reduces in occupied slots (ms)=5713
        Total time spent by all map tasks (ms)=52498
        Total time spent by all reduce tasks (ms)=5713
        Total vcore-milliseconds taken by all map tasks=52498
        Total vcore-milliseconds taken by all reduce tasks=5713
        Total megabyte-milliseconds taken by all map tasks=53757952
        Total megabyte-milliseconds taken by all reduce tasks=5850112
    Map-Reduce Framework
        Map input records=1665
        Map output records=5029
        Map output bytes=76784
        Map output materialized bytes=86865
        Input split bytes=295
        Combine input records=0
        Combine output records=0
        Reduce input groups=998
        Reduce shuffle bytes=86865
        Reduce input records=5029
        Reduce output records=998
        Spilled Records=10058
        Shuffled Maps =3
        Failed Shuffles=0
        Merged Map outputs=3
        GC time elapsed (ms)=847
        CPU time spent (ms)=3130
        Physical memory (bytes) snapshot=712916992
        Virtual memory (bytes) snapshot=8411308032
        Total committed heap usage (bytes)=444870656
    Shuffle Errors
        BAD_ID=0
        CONNECTION=0
        IO_ERROR=0
        WRONG_LENGTH=0
        WRONG_MAP=0
        WRONG_REDUCE=0
    File Input Format Counters 
        Bytes Read=66874
    File Output Format Counters 
        Bytes Written=24946
17/09/04 14:34:00 INFO streaming.StreamJob: Output directory: /user/test/gutenberg-output

可以发现运行成功,然后可以查看运行结果:

[hadoop@localhost hadoop-2.7.4]$ bin/hdfs dfs -cat  /user/test/gutenberg-output/part-00000
!   3
""; 6
"-//W3C//DTD    3
"//m.gutenberg.org/ebooks/20417.mobile";    1
"//m.gutenberg.org/ebooks/4300.mobile"; 1
"//m.gutenberg.org/ebooks/5000.mobile"; 1
"/ebooks/suggest/"; 3
"Load   3
"Quixote"</td>  3
"en_US";    6
"http://www.gutenberg.org/ebooks/20417";    1
"http://www.gutenberg.org/ebooks/4300"; 1
"http://www.gutenberg.org/ebooks/5000"; 1
"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">    3
"screen";   3
<Enter>.    3
<enter>">   3
<h>"    3
<s>"    3
...

可以看到结果了。
感谢:数据来源:可以是web日志,比如access.log,可以是爬虫爬来的数据,就要用python来做了。从数据来源中看能不能获取一些有用信息。
参考:
最经典的python在hadoop上使用教程
使用 python 构建基于 hadoop 的 mapreduce 日志分析平台

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值