泉州市建设工程交易网站,wordpress主题module,项目管理咨询公司,凡科网邮箱登陆Hadoop简介
众所周知#xff0c;我们已经进入了大数据时代#xff0c;每天都有PB级的数据需要处理、分析#xff0c;从中提取出有用的信息。Hadoop就是这一时代背景下的产物。它是Apache基金会下的开源项目#xff0c;受Google两篇论文的启发#xff0c;采用分布式的文件…Hadoop简介
众所周知我们已经进入了大数据时代每天都有PB级的数据需要处理、分析从中提取出有用的信息。Hadoop就是这一时代背景下的产物。它是Apache基金会下的开源项目受Google两篇论文的启发采用分布式的文件系统HDFS以及通用的MapReduce解决方案能够在数千台物理节点上进行分布式并行计算。
对于Hadoop的介绍这里不再赘述读者可以访问其官网或阅读Hadoop权威指南。
Hadoop项目是由Java语言编写的运行在JVM之上因此我们可以直接使用Clojure来编写MapReduce脚本这也是本文的主题。Hadoop集群的搭建不在本文讨论范围内而且运行MapReduce脚本也无需搭建测试环境。 clojure-hadoop类库
Hadoop提供的API是面向Java语言的如果不想在Clojure中过多地操作Java对象那就需要对API进行包装wrapper好在已经有人为我们写好了它就是clojure-hadoop。
从clojure-hadoop的项目介绍中可以看到它提供了不同级别的包装你可以选择完全规避对Hadoop类型和对象的操作使用纯Clojure语言来编写脚本也可以部分使用Hadoop对象以提升性能因为省去了类型转换过程。这里我们选择前一种即完全使用Clojure语言。
示例1Wordcount
Wordcount统计文本文件中每个单词出现的数量可以说是数据处理领域的“Hello, world!”。这一节我们就通过它来学习如何编写MapReduce脚本。
Leiningen 2
前几章我们使用的项目管理工具lein是1.7版的而前不久Leiningen 2已经正式发布了因此从本章开始我们的示例都会基于新版本。新版lein的安装过程也很简单
$ cd ~/bin
$ wget https://raw.github.com/technomancy/leiningen/stable/bin/lein
$ chmod 755 lein
$ lein repl
user其中lein repl这一步会下载lein运行时需要的文件包括Clojure 1.4。
新建项目
$ lein new cia-hadoop编辑project.clj文件添加依赖项clojure-hadoop 1.4.1尔后执行lein deps。
Map和Reduce
MapReduce简称mapred是Hadoop的核心概念之一。可以将其理解为处理问题的一种方式即将大问题拆分成多个小问题来分析和解决最终合并成一个结果。其中拆分的过程就是Map合并的过程就是Reduce。
以Wordcount为例将一段文字划分成一个个单词的过程就是Map。这个过程是可以并行执行的即将文章拆分成多个段落每个段落分别在不同的节点上执行划分单词的操作。这个过程结束后我们便可以统计各个单词出现的次数这也就是Reduce的过程。同样Reduce也是可以并发执行的。整个过程如下图所示 中间Shuffle部分的功能是将Map输出的数据按键排序交由Reduce处理。整个过程全部由Hadoop把控开发者只需编写Map和Reduce函数这也是Hadoop强大之处。
编写Map函数
在本示例中我们处理的原始数据是文本文件Hadoop会逐行读取并调用Map函数。Map函数会接收到两个参数key是一个长整型表示该行在整个文件中的偏移量很少使用value则是该行的内容。以下是将一行文字拆分成单词的Map函数
;; src/cia_hadoop/wordcount.clj(ns cia-hadoop.wordcount(:require [clojure-hadoop.wrap :as wrap][clojure-hadoop.defjob :as defjob])(:import [java.util StringTokenizer])(:use clojure-hadoop.job))(defn my-map [key value](map (fn [token] [token 1])(enumeration-seq (StringTokenizer. value))))可以看到这是一个纯粹的Clojure函数并没有调用Hadoop的API。函数体虽然只有两行但还是包含了很多知识点的
(map f coll)函数的作用是将函数f应用到序列coll的每个元素上并返回一个新的序列。如(map inc [1 2 3])会对每个元素做加1操作参考(doc inc)返回[2 3 4]。值得一提的是map函数返回的是一个惰性序列lazy sequence即序列元素不会一次性完全生成而是在遍历过程中逐个生成这在处理元素较多的序列时很有优势。
map函数接收的参数自然不会只限于Clojure内部函数我们可以将自己定义的函数传递给它
(defn my-inc [x]( x 1))(map my-inc [1 2 3]) ; - [2 3 4]我们更可以传递一个匿名函数给map。上一章提过定义匿名函数的方式是使用fn另外还可使用#(...)简写
(map (fn [x] ( x 1)) [1 2 3])
(map #( % 1) [1 2 3])对于含有多个参数的情况
((fn [x y] ( x y)) 1 2) ; - 3
(#( %1 %2) 1 2) ; - 3my-map中的(fn [token] [token 1])即表示接收参数token返回一个向量[token 1]其作用等价于#(vector % 1)。为何是[token 1]是因为Hadoop的数据传输都是以键值对的形式进行的如[apple 1]即表示“apple”这个单词出现一次。
StringTokenizer则是用来将一行文字按空格拆分成单词的。他的返回值是Enumeration类型Clojure提供了enumeration-seq函数可以将其转换成序列进行操作。
所以最终my-map函数的作用就是将一行文字按空格拆分成单词返回一个形如[[apple 1] [orange 1] ...]的序列。
编写Reduce函数
从上文的图表中可以看到Map函数处理完成后Hadoop会对结果按照键进行排序并使用key, [value1 value2 ...]的形式调用Reduce函数。在clojure-hadoop中Reduce函数的第二个参数是一个函数其返回结果才是值的序列
(defn my-reduce [key values-fn][[key (reduce (values-fn))]])和Map函数相同Reduce函数的返回值也是一个序列其元素是一个个[key value]。注意函数体中的(reduce f coll)是Clojure的内置函数其作用是取coll序列的第1、2个元素作为参数执行函数f将结果和coll序列的第3个元素作为参数执行函数f依次类推。因此(reduce [1 2 3])等价于( ( 1 2) 3)。
定义脚本
有了Map和Reduce函数我们就可以定义一个完整的脚本了
(defjob/defjob job:map my-map:map-reader wrap/int-string-map-reader:reduce my-reduce:input-format :text:output-format :text:compress-output false:replace true:input README.md:output out-wordcount)简单说明一下这些配置参数:map和:reduce分别指定Map和Reduce函数map-reader表示读取数据文件时采用键为int、值为string的形式:input-format至compress-output指定了输入输出的文件格式这里采用非压缩的文本形式方便阅览:replace表示每次执行时覆盖上一次的结果:input和:output则是输入的文件和输出的目录。
执行脚本
我们可以采用Clojure的测试功能来执行脚本
;; test/cia_hadoop/wordcount_test.clj(ns cia-hadoop.wordcount-test(:use clojure.testclojure-hadoop.jobcia-hadoop.wordcount))(deftest test-wordcount(is (run job)))尔后执行
$ lein test cia-hadoop.wordcount-test
...
13/02/14 00:25:52 INFO mapred.JobClient: map 0% reduce 0%
..
13/02/14 00:25:58 INFO mapred.JobClient: map 100% reduce 100%
...
$ cat out-wordcount/part-r-00000
...
java 1
lein 3
locally 2
on 1
...如果想要将MapReduce脚本放到Hadoop集群中执行可以采用以下命令
$ lein uberjar
$ hadoop jar target/cia-hadoop-0.1.0-SNAPSHOT-standalone.jar clojure_hadoop.job -job cia-hadoop.wordcount/job示例2统计浏览器类型
下面我们再来看一个更为实际的示例从用户的访问日志中统计浏览器类型。
需求概述
用户访问网站时页面中会有段JS请求将用户的IP、User-Agent等信息发送回服务器并记录成文本文件的形式
{stamp: 1346376858286, ip: 58.22.113.189, agent: Mozilla/5.0 (iPad; CPU OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A405 Safari/7534.48.3}
{stamp: 1346376858354, ip: 116.233.51.2, agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)}
{stamp: 1346376858365, ip: 222.143.28.2, agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)}
{stamp: 1346376858423, ip: 123.151.144.40, agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11}我们要做的是从User-Agent中统计用户使用的浏览器类型所占比例包括IE、Firefox、Chrome、Opera、Safari、以及其它。
User-Agent中的浏览器类型
由于一些历史原因User-Agent中的信息是比较凌乱的浏览器厂商会随意添加信息甚至仿造其它浏览器的内容。因此在过滤时我们需要做些额外的处理。Mozilla的这篇文章很好地概括了如何从User-Agent中获取浏览器类型大致如下
IE: MSIE xyzFirefox: Firefox/xyzChrome: Chrome/xyzOpera: Opera/xyzSafari: Safari/xyz, 且不包含 Chrome/xyz 和 Chromium/xyz
解析JSON字符串
Clojure除了内置函数之外周边还有一个名为clojure.contrib的类库其中囊括了各类常用功能包括JSON处理。目前clojure.contrib中的各个组件已经分开发行读者可以到 https://github.com/clojure 中浏览。
处理JSON字符串时首先在项目声明文件中添加依赖项[org.clojure/data.json 0.2.1]然后就能使用了
user (require [clojure.data.json :as json])
user (json/read-str {\a\:1,\b\:2})
{a 1, b 2}
user (json/write-str [1 2 3])
[1,2,3]正则表达式
Clojure提供了一系列的内置函数来使用正则表达式其实质上是对java.util.regex命名空间的包装。
user (def ptrn #[0-9]) ; #...是定义正则表达式对象的简写形式
user (def ptrn (re-pattern [0-9])) ; 和上式等价
user (re-matches ptrn 123) ; 完全匹配
123
user (re-find ptrn a123) ; 返回第一个匹配项
123
user (re-seq ptrn a123b456) ; 返回匹配项序列惰性序列
(123 456)
user (re-find #([a-z])/([0-9]) a/1) ; 子模式
[a/1 a 1]
user (def m (re-matcher #([a-z])/([0-9]) a/1 b/2)) ; 返回一个Matcher对象
user (re-find m) ; 返回第一个匹配
[a/1 a 1]
user (re-groups m) ; 获取当前匹配
[a/1 a 1]
user (re-find m) ; 返回下一个匹配或nil
[b/2 b 2]Map函数
(defn json-decode [s](try(json/read-str s)(catch Exception e)))(def rule-set {ie (partial re-find #(?i)MSIE [0-9])chrome (partial re-find #(?i)Chrome/[0-9])firefox (partial re-find #(?i)Firefox/[0-9])opera (partial re-find #(?i)Opera/[0-9])safari #(and (re-find #(?i)Safari/[0-9] %)(not (re-find #(?i)Chrom(e|ium)/[0-9] %)))})(defn get-type [ua](if-let [rule (first (filter #((second %) ua) rule-set))](first rule)other))(defn my-map [key value](when-let [ua (get (json-decode value) agent)][[(get-type ua) 1]]))json-decode函数是对json/read-str的包装当JSON字符串无法正确解析时返回nil而非异常终止。
rule-set是一个map类型键是浏览器名称值是一个函数这里都是匿名函数。partial用于构造新的函数(partial 1)和#( 1 %)、(fn [x] ( 1 x))是等价的可以将其看做是为函数的第一个参数定义了默认值。正则表达式中的(?i)表示匹配时不区分大小写。
get-type函数中(filter #((second %) ua) rule-set)会用rule-set中的正则表达式逐一去和User-Agent字符串进行匹配并返回第一个匹配项也就是浏览器类型没有匹配到的则返回other。
单元测试
我们可以编写一组单元测试来检验上述my-map函数是否正确
;; test/cia_hadoop/browser_test.clj(ns cia-hadoop.browser-test(:use clojure.testclojure-hadoop.jobcia-hadoop.browser))(deftest test-my-map(is ( [[ie 1]] (my-map 0 {\agent\:\MSIE 6.0\})))(is ( [[chrome 1]] (my-map 0 {\agent\:\Chrome/20.0 Safari/6533.2\})))(is ( [[other 1]] (my-map 0 {\agent\:\abc\})))(is (nil? (my-map 0 {))))(deftest test-browser(is (run job)))其中deftest和is都是clojure.test命名空间下定义的。
$ lein test cia-hadoop.browser-test小结
本章我们简单介绍了Hadoop这一用于大数据处理的开源项目以及如何借助clojure-hadoop类库编写MapReduce脚本并在本地和集群上运行。Hadoop已经将大数据处理背后的种种细节都包装了起来用户只需编写Map和Reduce函数而借助Clojure语言这一步也变的更为轻松和高效。Apache Hadoop是一个生态圈其周边有很多开源项目像Hive、HBase等这里再推荐一个使用Clojure语言在Hadoop上执行查询的工具cascalog。它的作者是Nathan Marz也是我们下一章的主题——Storm实时计算框架——的作者。
本文涉及到的源码可以到 https://github.com/jizhang/blog-demo/tree/master/cia-hadoop 中查看。 文章转载自: http://www.morning.tsynj.cn.gov.cn.tsynj.cn http://www.morning.xfyjn.cn.gov.cn.xfyjn.cn http://www.morning.tdttz.cn.gov.cn.tdttz.cn http://www.morning.bbyqz.cn.gov.cn.bbyqz.cn http://www.morning.ckhry.cn.gov.cn.ckhry.cn http://www.morning.wlggr.cn.gov.cn.wlggr.cn http://www.morning.rkypb.cn.gov.cn.rkypb.cn http://www.morning.stwxr.cn.gov.cn.stwxr.cn http://www.morning.rcjyc.cn.gov.cn.rcjyc.cn http://www.morning.sqnxk.cn.gov.cn.sqnxk.cn http://www.morning.yrbp.cn.gov.cn.yrbp.cn http://www.morning.yrmpz.cn.gov.cn.yrmpz.cn http://www.morning.bnmfq.cn.gov.cn.bnmfq.cn http://www.morning.txmlg.cn.gov.cn.txmlg.cn http://www.morning.qdscb.cn.gov.cn.qdscb.cn http://www.morning.xsymm.cn.gov.cn.xsymm.cn http://www.morning.ffcsr.cn.gov.cn.ffcsr.cn http://www.morning.qichetc.com.gov.cn.qichetc.com http://www.morning.dmthy.cn.gov.cn.dmthy.cn http://www.morning.xqbbc.cn.gov.cn.xqbbc.cn http://www.morning.gjtdp.cn.gov.cn.gjtdp.cn http://www.morning.jgykx.cn.gov.cn.jgykx.cn http://www.morning.lpcpb.cn.gov.cn.lpcpb.cn http://www.morning.dnhdp.cn.gov.cn.dnhdp.cn http://www.morning.ftync.cn.gov.cn.ftync.cn http://www.morning.jqpq.cn.gov.cn.jqpq.cn http://www.morning.kryxk.cn.gov.cn.kryxk.cn http://www.morning.gjcdr.cn.gov.cn.gjcdr.cn http://www.morning.spnky.cn.gov.cn.spnky.cn http://www.morning.rwbh.cn.gov.cn.rwbh.cn http://www.morning.qnklx.cn.gov.cn.qnklx.cn http://www.morning.ffmx.cn.gov.cn.ffmx.cn http://www.morning.zmpsl.cn.gov.cn.zmpsl.cn http://www.morning.lbhck.cn.gov.cn.lbhck.cn http://www.morning.yrddl.cn.gov.cn.yrddl.cn http://www.morning.rfpq.cn.gov.cn.rfpq.cn http://www.morning.nmfxs.cn.gov.cn.nmfxs.cn http://www.morning.kltmt.cn.gov.cn.kltmt.cn http://www.morning.dxhdn.cn.gov.cn.dxhdn.cn http://www.morning.srkwf.cn.gov.cn.srkwf.cn http://www.morning.xpmhs.cn.gov.cn.xpmhs.cn http://www.morning.stph.cn.gov.cn.stph.cn http://www.morning.zycll.cn.gov.cn.zycll.cn http://www.morning.shxrn.cn.gov.cn.shxrn.cn http://www.morning.zxznh.cn.gov.cn.zxznh.cn http://www.morning.mnwmj.cn.gov.cn.mnwmj.cn http://www.morning.ybnzn.cn.gov.cn.ybnzn.cn http://www.morning.ctbr.cn.gov.cn.ctbr.cn http://www.morning.ywpwq.cn.gov.cn.ywpwq.cn http://www.morning.rtlg.cn.gov.cn.rtlg.cn http://www.morning.fsqbx.cn.gov.cn.fsqbx.cn http://www.morning.mynbc.cn.gov.cn.mynbc.cn http://www.morning.mlmwl.cn.gov.cn.mlmwl.cn http://www.morning.zlwg.cn.gov.cn.zlwg.cn http://www.morning.zqfz.cn.gov.cn.zqfz.cn http://www.morning.dqpnd.cn.gov.cn.dqpnd.cn http://www.morning.ksggr.cn.gov.cn.ksggr.cn http://www.morning.tpnxj.cn.gov.cn.tpnxj.cn http://www.morning.wmpw.cn.gov.cn.wmpw.cn http://www.morning.bccls.cn.gov.cn.bccls.cn http://www.morning.rpkg.cn.gov.cn.rpkg.cn http://www.morning.zrjzc.cn.gov.cn.zrjzc.cn http://www.morning.pjzcp.cn.gov.cn.pjzcp.cn http://www.morning.hdwjb.cn.gov.cn.hdwjb.cn http://www.morning.mnygn.cn.gov.cn.mnygn.cn http://www.morning.kkjlz.cn.gov.cn.kkjlz.cn http://www.morning.zwzlf.cn.gov.cn.zwzlf.cn http://www.morning.ywxln.cn.gov.cn.ywxln.cn http://www.morning.rfhwc.cn.gov.cn.rfhwc.cn http://www.morning.ddrdt.cn.gov.cn.ddrdt.cn http://www.morning.rykgh.cn.gov.cn.rykgh.cn http://www.morning.rmpkn.cn.gov.cn.rmpkn.cn http://www.morning.swimstaracademy.cn.gov.cn.swimstaracademy.cn http://www.morning.qrsrs.cn.gov.cn.qrsrs.cn http://www.morning.mooncore.cn.gov.cn.mooncore.cn http://www.morning.rszt.cn.gov.cn.rszt.cn http://www.morning.mfzyn.cn.gov.cn.mfzyn.cn http://www.morning.slpcl.cn.gov.cn.slpcl.cn http://www.morning.ns3nt8.cn.gov.cn.ns3nt8.cn http://www.morning.zhishizf.cn.gov.cn.zhishizf.cn