??xml version="1.0" encoding="utf-8" standalone="yes"?> Hadoop实施已经有快一个月了,对Hadoop的概느解、用,Linux与shell脚本Q甚至mysql都有了更多的理解?br /> 目背景Q用于互联网信息攉后的关键词匹配与内容提取?/span> 主要pȝ架构分ؓ互联|爬虫、分析、业务应用三块: 单架构描q?/span> ׃我在当中的角色主要负责分析架构的搭徏Q所以其他两块都d单,下面也不会过多的描述?br /> Hadoop理解Q提到Hadoop都想到的是云、分布式计算Q在一D|间的实施之后有了一些具体的理解?/span> Hadoop的优势: 针对性能指标Q当业务数据量总量或增速上升到一定别,依靠关系型数据库一定无法支持。对于非关系型数据库Q包括Nosql和Solr一cd储方式,E显复杂Q对于机器集性能要求偏高Q相对于文gpȝQ。从数据使用模式上来Ԍ目前量数据的常常是不包含复杂逻辑的简单统计整理(比如上述pȝ中的关键词匹配)。这时候文件系l的优势反而比较明显(l构单,逻辑单)?/span> 如上q系l的应用场景是怎么L呢,在一个强大的爬虫pȝ之下Q每个小时的数据增量在G?0G的别,需要搜索所有的文gQ获取关键字的匹配,q且对匹配内容进行摘要。很cM我们windows里面的搜索功能,需要解决的是如何在这样增q的文gpȝ之下Q如何满业务系l的需求?br /> ?/span>分析pȝ有什么要?/span>呢? l 能够建立集群Q分布式的保存数据文件内容(l一控制Q可配置Q?/span> l 有一定的保护机制Q保证数据或节点丢失不会影响pȝ使用?/span> l 如果有一个Q务脚本执行框架机制就好了Q用于ƈ行计)?/span> l 能够q行节点间的数据均衡?/span> l 能够单的查看所有的状态与日志Qweb客户端) 可能主要是这些了。若自己实现Q确实是个复杂而庞大的工程Q现在我们有了Hadoop?br /> pȝ物理架构Q?/span> 我们使用了一台服务器Q利用虚拟化Q安装了7?4x位的CentOS。一个NamenodeQ?个DatanodeQ复制数讄?。每个系l分配到一个cpuQ?G内存QDatanode挂蝲?00G的存储空间?/span> 理想的Hadoop的搭建环境,参照《Best Practices for Selecting Apache Hadoop Hardware》(http://hortonworks.com/blog/best-practices-for-selecting-apache-hadoop-hardware/Q一文,以及一些其他的文章?/span> CPUQ最好是双CPUQ?核左叟뀂不用太高了?/span> 内存Q推?8GQ但?G应该可以运行Hadoop了?/span> 盘Q?200转的SATA盘卛_QHadoop很占I间Q所以尽量加?/span> |络Q内部的数据交换要求非常高,内网最好是千兆|卡Q带宽ؓ1GB?br /> 理想与现实,有钱与没钱,呵呵?br /> pȝ软g架构Q?/span> HadoopQ版本用的?.0.3Q再下来是2了,Z量化应用,所以不考虑2的新Ҏ。对Hadoop没有做太多的讄Q基本基于默认?0为NamenodeQ?1-76为Datanode?/span> JDKQ?.6.0_33 Q?4xQ?br /> pȝ实施q程Q?/span> HDFS部分Q?/span> 爬虫抓取数据Q整理后存放?0文g服务器,70以外部挂载的形式d。网|件比较小Q假如直接写入Hadoop对Namenode负蝲q大Q所以入库前合ƈQ将每小时网|合成Z个文件写入HDFSQ由于区分类别,所以每时基本写入10个文件左叻I总量?-8GQ耗时?0-50分钟。(q个q程中,׃爬虫的IOq于频繁Q导致文件读取困难,所以做了定时Q务,每小时启动一ơ,需要处理的文g先拷贝到临时区域Q合q入库之后再删除。此处应该是受到单核cpu的限Ӟ所有操作均是串行,包括拯QcpQ和合ƈ入库QjavaQ,所以Namenode严重配置E高。) 此处没有太多问题?/span> MapReduce部分Q?/span> 写入完成后,q行分析工作QMapReduce。此处的工作q程为:数据库定时生成关键词列表文g。Job执行时会d列表文gQ匹配指定范围内的HDFS文gQ过M时Q,匚w出对应的表达式与HTMLQMapq程l束。在Reduce阶段Q会Map的所有数据入数据库(MysqlQ?/span> 此处出现q一些问题,记录下来?/span> 1. Reduce阶段需要加载Mysql的第三方驱动包。我在三个环境测试过Q公司、家里、发布环境)Q?nbsp;-libjars 一定可以,有的地方不需要也可以。不明确Q怀疑与HADOOP_HOME环境变量有关?/span> 2. MRq程中用log4j打印日志Q在Hadoop临时目录Q如果你没有配置dfs.name.dirQdfs.data.dir,mapred.local.dir.mapred.system.dir{目录,q些都会在hadoop.tmp.dir当中Q我偷懒都没配|)mapred文g夹中查看一下?/span> 整个q程实际上还是比较简单的Q基本编码量在Job的部分,但是一个Java文g够了。在目前初阶段应该q是比较好用的。现在还没有试Job的执行效率。完成后会l记录下来。有什么问题可以提出。我惛_什么也会在本文l箋更新?/span> g资源Q?/span> 三台CentOS5.6虚拟机(VmwareQ?/span> 本机 windows7 64x 基本资源配置Q?/span> 三台虚拟机均是克隆自同一个镜?/span> 已经安装?/span>Java环境Q?/span>jdk1.6.0_25Q?/span> Hadoop路径?/span>/usr/hadoop/hadoop-0.20.205.0 操作步骤Q?/span> 1、机器名U规?/span> ip分别?/span>128?/span>129?/span>130Q将128讄?/span>masterQ其他设|ؓslave 修改 /etc/sysconfig/network /etc/hosts 两处配置Q名U分别ؓhadoop-master\hadoop-slave01\hadoop-slave02 注意Q此处名U最好不用用下划线Q有可能引发namenode的启动异常?/span> 2、修?/span>Hadoop配置 ?/span>master节点?/span>conf中修?/span>master?/span>slave文gQ分别ؓ机器?/span>ip地址 修改master节点?/span>conf中: core-site.xml <property> <name>fs.default.name</name> <value>hdfs://ip-master:9000</value> </property> mapred-site.xml <property> <name>mapred.job.tracker</name> <value>master:9001</value> </property> hdfs-site.xm <property> <name>dfs.replication</name> <value>2</value> </property> 注意此处的端口号均ؓ默认?/span> 3、徏?/span>m-s之间?/span>sshq接 首先master?/span>slave机器都需要进?/span>ssh信Q文g生成Q执行如下命令: $ ssh-keygen -t rsa 中间需要输入的地方直接回RQ接受缺省值即?/span> ׃使用root用户dQ所以密钥文件生成在 /root/.ssh/文g夹下Q存有一对密?/span>id_dsa?/span>id_dsa.pub?/span> 此处id_dsaQ私钥)必须为其他用户不可读Q所以文件属性应当是600 ?/span>master机器执行Q?/span> ?/span>id_dsa.pubQ公钥)复制?/span> authorized_keys $ cp id_dsa.pub authorized_keys 如果是多台机器需?/span>,无密码登?/span>,则各自机器生公钥追加到authorized_keys卛_. 使用scp协议覆盖slave端的密钥文g夹,使得slave机器信Q来自master的连?/span>: $ scp /root/.ssh/* ip-slave:/root/.ssh 4、启动服?/span> ?/span>$HADOOP_HOME/bin下的所有文件给与执行权限: $ chmod 777 bin master作ؓnamenod需要执行如下脚本: $HADOOP_HOME/bin/hadoop namenode –format 完成后执?/span> $HADOOP_HOME/bin/start-all.sh 5、问题检?/span> ?/span>Hadoop根目录下?/span>logs文g中,查各个服务日志的启动情况 6、其他情况说明: Q: $HADOOP_HOME is deprecated A: 基本不会产生M影响。由于脚本启动时讄了该环境变量Q就会提C用户原有环境变量失效。可以取消环境变量设|,或者直接去bin/hadoop中找到这句话Q去掉即?/span> Q: 无效的选项 -jvm / Unrecognized option: -jvm A: 在?/span>root用户d?/span> bin/hadoop 脚本׃q行判断Q加?/span>-jvm参数。此处是Zq入jsvcQ?/span>http://commons.apache.org/daemon/jsvc.htmlQ,此处q不定是否bugQ也不再q行详细的追溯,解决Ҏ是q入 bin/hadoop 脚本?/span> 扑ֈ jvm 参数q去掉?/span> ZNode Znode是核心l构QZookeeper服务中是由大量的Znode构成。Znode一般是由客L建立和修改,作ؓ信息或标志的载体Q甚xw就是标志?/span> Znode可以讄为持久(PERSISTENTQ或临时QEPHEMERALQ,区别在于临时的节点若断开q接后就自动删除。徏立节Ҏ可选择是否使用序列号命名(SEQUENTIALQ,若启用则会自动在节点名后加入唯一序列~号?/span> Session 作ؓ客户端和Zookeeper服务之间交互的凭证?/span> Watch 当客L对节点信息进行查询操作之后,可以选择是否讄一个Watch。其作用是当本ơ查询的数据在服务器端发生变化之后,会对讄Watch的客L发送通知。一ơ发送之后,将删除该WatchQ以后的变更或不再设|Watch则不会通知?/span> ACLs 节点的权限限制用ACLQ如增删Ҏ操作?/span> 1?/span>下蝲对应版本Ltar.gz文g 2?/span>使用 tar xzvf zookeeper-3.4.2.tar.gz -C ./ 解压 3?/span>讄Q将conf/zoo.example.cfg复制到conf/zoo.cfg或者手动徏立一个新的?/span> 4?/span>启动Zookeeper服务Qbin/zkServer.sh start 5?/span>启动客户端连接:bin/zkCli.sh -server 127.0.0.1:2181Q此处在本机Q且使用了默认端口,且在Java环境中) 6?/span>使用命oQls、get、set{?/span> 7?/span>关闭Zookeeper服务Qbin/zkServer.sh stop 代码~写部分比较单,因ؓ暴露的接口很,主要复杂在于目如何使用节点以及节点信息?/span> 启动Zookeeper服务之后Q客L代码q行节点的增删,Watch的设|,内容的改查等?/span> 此处查看官方的《Programming with ZooKeeper - A basic tutorial》部分,当中举了两个例子来模拟分布式pȝ的应用?/span> 代码基本没有问题Q唯一需要注意的是Q若之间按照原版q行调试Ӟ有可能在调用 q句代码时会出现一个异常,当中包括“KeeperErrorCode = ConnectionLoss for”?/span> q个问题引v的原因可以看一下代?/span> 最后一行有打印出Zookeeper目前的信息,若未修改的原代码Q此处的State应当是CONECTING。连接中的时候去验证是否存在节点会报错。解决的Ҏ也很单,是{到Zookeeper客户端以及完全连接上服务器,State为CONECTED之后再进行其他操作。给Z码示例: q样可以正运行代码了?/span> 此处是ؓ引用Q原地址为(http://rdc.taobao.com/team/jm/archives/1232 Q?/span> ZooKeeper是一个高可用的分布式数据理与系l协调框架。基于对Paxos法的实玎ͼ使该框架保证了分布式环境中数据的Z致性,也正是基于这LҎ,使得zookeeper能够应用于很多场景。网上对zk的用场景也有不介l,本文结合作者n边的目例子Q系l的对zk的用场景进行归cMl?nbsp;值得注意的是Qzkq不是生来就些场景设计,都是后来众多开发者根据框架的Ҏ,摸烦出来的典型用方法。因此,也非常欢q你分n你在ZK使用上的奇技淫y?/span> 场景cd 典型场景描述QZKҎ,使用ҎQ?/span> 应用中的具体使用 数据发布与订?/span> 发布与订阅即所谓的配置理Q顾名思义是数据发布到zk节点上,供订阅者动态获取数据,实现配置信息的集中式理和动态更新。例如全局的配|信息,地址列表{就非常适合使用?/span> 1. 索引信息和集中机器节点状态存攑֜zk的一些指定节点,供各个客L订阅使用?. pȝ日志Q经q处理后的)存储Q这些日志通常2-3天后被清除?nbsp; 3. 应用中用到的一些配|信息集中管理,在应用启动的时候主动来获取一ơ,q且在节点上注册一个WatcherQ以后每ơ配|有更新Q实旉知到应用,获取最新配|信息?/span> 4. 业务逻辑中需要用到的一些全局变量Q比如一些消息中间g的消息队列通常有个offsetQ这个offset存放在zk上,q样集群中每个发送者都能知道当前的发送进度?/span> 5. pȝ中有些信息需要动态获取,q且q会存在人工手动M改这个信息。以前通常是暴露出接口Q例如JMX接口Q有了zk后,只要这些信息存攑ֈzk节点上即可?/span> Name Service q个主要是作为分布式命名服务Q通过调用zk的create node apiQ能够很Ҏ创徏一个全局唯一的pathQ这个path可以作Z个名U?/span> 分布通知/协调 ZooKeeper中特有watcher注册与异步通知机制Q能够很好的实现分布式环境下不同pȝ之间的通知与协调,实现Ҏ据变更的实时处理。用方法通常是不同系l都对ZK上同一个znodeq行注册Q监听znode的变化(包括znode本n内容及子节点的)Q其中一个系lupdate了znodeQ那么另一个系l能够收到通知Qƈ作出相应处理?/span> 1. 另一U心x机Ӟ系l和被检系l之间ƈ不直接关联v来,而是通过zk上某个节点关联,大大减少pȝ耦合?. 另一U系l调度模式:某系l有控制台和推送系l两部分l成Q控制台的职责是控制推送系l进行相应的推送工作。管理h员在控制C的一些操作,实际上是修改了ZK上某些节点的状态,而zk把q些变化通知l他们注册Watcher的客LQ即推送系l,于是Q作出相应的推送Q务?nbsp; 3. 另一U工作汇报模式:一些类gd分发pȝQ子d启动后,到zk来注册一个时节点,q且定时自qq度q行汇报Q将q度写回q个临时节点Q,q样d理者就能够实时知道dq度?/span> MQ用zookeeper来进行分布式通知和协调能够大大降低系l之间的耦合?/span> 分布式锁 分布式锁Q这个主要得益于ZooKeeper为我们保证了数据的强一致性,即用户只要完全相信每时每刻,zk集群中Q意节点(一个zk serverQ上的相同znode的数据是一定是相同的。锁服务可以分ؓ两类Q?/span>一个是保持独占Q另一个是控制时序?/span> 所谓保持独占,是所有试图来获取q个锁的客户端,最l只有一个可以成功获得这把锁。通常的做法是把zk上的一个znode看作是一把锁Q通过create znode的方式来实现。所有客L都去创徏 /distribute_lock 节点Q最l成功创建的那个客户端也x有了q把锁?/span> 控制时序Q就是所有视图来获取q个锁的客户端,最l都是会被安排执行,只是有个全局时序了。做法和上面基本cMQ只是这?nbsp;/distribute_lock 已经预先存在Q客L在它下面创徏临时有序节点Q这个可以通过节点的属性控ӞCreateMode.EPHEMERAL_SEQUENTIAL来指定)。Zk的父节点Q?distribute_lockQ维持一份sequence,保证子节点创建的时序性,从而也形成了每个客L的全局时序?/span> 集群理 1. 集群机器监控Q这通常用于那种寚w中机器状态,机器在线率有较高要求的场景,能够快速对集群中机器变化作出响应。这L场景中,往往有一个监控系l,实时集机器是否存zR过ȝ做法通常是:监控pȝ通过某种手段Q比如pingQ定时检每个机器,或者每个机器自己定时向监控pȝ汇报“我还zȝ”?nbsp;q种做法可行Q但是存在两个比较明昄问题Q?. 集群中机器有变动的时候,牵连修改的东西比较多?. 有一定的延时?nbsp; 利用ZooKeeper有两个特性,可以实时另一U集机器存zL监控系l:a. 客户端在节点 x 上注册一个WatcherQ那么如?nbsp;x 的子节点变化了,会通知该客L。b. 创徏EPHEMERALcd的节点,一旦客L和服务器的会话结束或q期Q那么该节点׃消失?/span> 例如Q监控系l在 /clusterServers 节点上注册一个WatcherQ以后每动态加机器Q那么就往 /clusterServers 下创Z?nbsp;EPHEMERALcd的节点:/clusterServers/{hostname}. q样Q监控系l就能够实时知道机器的增减情况,至于后箋处理是监控pȝ的业务了?/span> 在分布式环境中,相同的业务应用分布在不同的机器上Q有些业务逻辑Q例如一些耗时的计,|络I/O处理Q,往往只需要让整个集群中的某一台机器进行执行,其余机器可以׃nq个l果Q这样可以大大减重复劳动,提高性能Q于是这个master选D便是q种场景下的到的主要问题?/span> 利用ZooKeeper的强一致性,能够保证在分布式高ƈ发情况下节点创徏的全局唯一性,卻I同时有多个客Lh创徏 /currentMaster 节点Q最l一定只有一个客Lh能够创徏成功?/span> 利用q个Ҏ,p很轻易的在分布式环境中进行集选取了?/span> 另外Q这U场景演化一下,是动态Master选D。这p用到 EPHEMERAL_SEQUENTIALcd节点的特性了?/span> 上文中提刎ͼ所有客L创徏hQ最l只有一个能够创建成功。在q里E微变化下,是允许所有请求都能够创徏成功Q但是得有个创徏序Q于是所有的h最l在ZK上创建结果的一U可能情冉|q样Q?nbsp;/currentMaster/{sessionId}-1 , /currentMaster/{sessionId}-2 , /currentMaster/{sessionId}-3 ….. 每次选取序列h的那个机器作ؓMasterQ如果这个机器挂了,׃他创建的节点会马上小Ӟ那么之后最的那个机器是Master了?/span> 1. 在搜索系l中Q如果集中每个机器都生成一份全量烦引,不仅耗时Q而且不能保证彼此之间索引数据一致。因此让集群中的Master来进行全量烦引的生成Q然后同步到集群中其它机器?. 另外QMaster选D的容灾措施是Q可以随时进行手动指定masterQ就是说应用在zk在无法获取master信息Ӟ可以通过比如http方式Q向一个地方获取master?/span> 分布式队?/span> 队列斚wQ我目前感觉有两U,一U是常规的先q先出队列,另一U是要等到队列成员聚齐之后的才统一按序执行。对于第二种先进先出队列Q和分布式锁服务中的控制时序场景基本原理一_q里不再赘述?nbsp; W二U队列其实是在FIFO队列的基上作了一个增强。通常可以?nbsp;/queue q个znode下预先徏立一?queue/num 节点Qƈ且赋gؓnQ或者直接给/queue赋值nQ,表示队列大小Q之后每ơ有队列成员加入后,判断下是否已经到达队列大小Q决定是否可以开始执行了。这U用法的典型场景是,分布式环境中Q一个大dTask AQ需要在很多子Q务完成(或条件就l)情况下才能进行。这个时候,凡是其中一个子d完成Q就l)Q那么就?nbsp;/taskList 下徏立自q临时时序节点QCreateMode.EPHEMERAL_SEQUENTIALQ,?nbsp;/taskList 发现自己下面的子节点满指定个数Q就可以q行下一步按序进行处理了?/span> ׃公司的业务需要,要在|络攉|页之后对网进行结构化的解析,q个l构化过E希望能够基?/span>HDFSq且使用MR法实现?/span> 我虚拟了一个需求,针对http://hadoop.apache.org/common/releases.html 面Q假讑ַl下载了面q入库。要求最l体现的数据?/span> “版本?/span>+完整链接Q即a标签全部内容Q?#8221; 的结构?/span> 伪分布式环境搭徏在虚拟机上,操作pȝ?/span>centos5.5Q?/span>hadoop的版本是1.0.0. 插入书中的一些环境搭建的介绍 书中?/span>2.1节中介绍了每个进E的作用?/span>2.2节中?/span>ssh讄也比较重要,否则好像会一直提CZ输入密码?/span>2.3.2节介l了伪分布式的配|方式,?/span>core-site.xmlQ?/span>mapred-site.xmlQ?/span>hdfs-site.xmlq行配置之后Q需要对namenode节点q行格式化?/span> bin/hadoop namenode –format hadoop的根目录?/span>/usr/local/hadoop-1.0.0Q直接启?/span>start-all.sh [root@localhost hadoop-1.0.0]# ./bin/start-all.sh 启动成功后?/span>jps命o jdk工?/span>jps介绍 jps(Java Virtual Machine Process Status Tool)?/span>JDK 1.5提供的一个显C当前所?/span>javaq程pid的命令,单实用,非常适合?/span>linux/unixq_上简单察看当?/span>javaq程的一些简单情c?/span> jps存放?/span>JAVA_HOME/bin/jps [root@localhost hadoop-1.0.0]# jps 5694 SecondaryNameNode 5461 NameNode 5578 DataNode 6027 Jps 5784 JobTracker 5905 TaskTracker q几个进E是非常重要的。很多时候出现意外就是因为某Ҏ务未启动或异常。可以看C面的命o上打印出日志位置。出现异常后可以在日志中查看详细的堆栈信息?/span> xQ?/span>hadoop已经启动Q环境已l准备就l?/span> 下面准备我们的测试数据,目标页面的html保存?/span>news.txtQ伪分布式也同样支持hdfsQ所以我们?/span> fs –put ?/span>news.txt存入hdfs中?/span> [root@localhost hadoop-1.0.0]# ./bin/hadoop fs -put /mnt/hgfs/shared/news.txt /user/root [root@localhost hadoop-1.0.0]# ./bin/hadoop fs -lsr /userdrwxr-xr-x - root supergroup 0 2012-04-01 11:22 /user/root -rw-r--r-- 1 root supergroup 3935 2012-04-01 11:22 /user/root/news.txt 实现的代码在eclipse中?/span>maven打包Q上传至虚拟机?/span> 文g?/span>com.suntang.analyse.hadoop-0.0.1.jar?br />使用hadoop的中的jar命o调用该jar文g?br /> 12/04/01 14:40:04 INFO input.FileInputFormat: Total input paths to process : 1 12/04/01 14:40:05 INFO mapred.JobClient: Running job: job_201204011420_0001 12/04/01 14:40:06 INFO mapred.JobClient: map 0% reduce 0% 12/04/01 14:40:19 INFO mapred.JobClient: map 100% reduce 0% 12/04/01 14:40:31 INFO mapred.JobClient: map 100% reduce 100% 12/04/01 14:40:37 INFO mapred.JobClient: Job complete: job_201204011420_0001 … 此处注意我犯的一个错误: [root@localhost hadoop-1.0.0]# ./bin/hadoop jar com.suntang.analyse.hadoop-0.0.1.jar AnalyseJob -libjars hadoop-core-1.0.0.jar /user/root/news.txt output_root_test Exception in thread "main" java.lang.ClassNotFoundException: AnalyseJob 提示找不到类Q因为我忘了写完整类名,命o应该改ؓ 此处q行可能出现另外一个错误。在命o行中出现 12/04/01 14:01:38 INFO mapred.JobClient: Task Id : attempt_201204011356_0001_m_000001_0, Status : FAILED java.lang.Throwable: Child Error at org.apache.hadoop.mapred.TaskRunner.run(TaskRunner.java:271) Caused by: java.io.IOException: Creation of symlink from /mnt/hgfs/shared/hadoop-1.0.0/libexec/../logs/userlogs/job_201204011356_0001/attempt_201204011356_0001_m_000001_0 to 。。?/span> ׃打全了,重点在与 执行完成后可?/span>hdfs中查看结果,查看目录l构?/span> -rw-r--r-- 1 root supergroup 0 2012-04-01 14:40 /user/root/output_root_test/_SUCCESS drwxr-xr-x - root supergroup 0 2012-04-01 14:40 /user/root/output_root_test/_logs drwxr-xr-x - root supergroup 0 2012-04-01 14:40 /user/root/output_root_test/_logs/history -rw-r--r-- 1 root supergroup 13634 2012-04-01 14:40 /user/root/output_root_test/_logs/history/job_201204011420_0001_1333262405103_root_ccAnalyseJob -rw-r--r-- 1 root supergroup 20478 2012-04-01 14:40 /user/root/output_root_test/_logs/history/job_201204011420_0001_conf.xml -rw-r--r-- 1 root supergroup 3580 2012-04-01 14:40 /user/root/output_root_test/part-r-00000 /user/root/output_root_test/part-r-00000即ؓ最l结果文件?/span> ======================================================================= 附加AnalyseJob代码 package com.suntang.analyse.hadoop; import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configured; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.LongWritable; 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.input.TextInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat; import org.apache.hadoop.util.Tool; import org.apache.hadoop.util.ToolRunner; public class AnalyseJob extends Configured implements Tool { public static class MapClass extends Mapper<LongWritable, Text, Text, Text> { @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { // TODO Auto-generated method stub // super.map(key, value, context); if (value.toString().matches("<a[^>]*>.*?release.*?</a>")) context.write( new Text(value.toString().substring( value.toString().indexOf("release") + 8, value.toString().indexOf("available") - 1)), value); } } public static class ReduceClass extends Reducer<Text, Text, Text, Text> { @Override protected void reduce(Text arg0, Iterable<Text> arg1, Context arg2) throws IOException, InterruptedException { // TODO Auto-generated method stub // super.reduce(arg0, arg1, arg2); arg2.write(arg0, arg1.iterator().next()); } } public int run(String[] args) throws Exception { Configuration conf = getConf(); Job job = new Job(conf, "myAnalyseJob"); job.setJarByClass(getClass()); Path in = new Path(args[0]); Path out = new Path(args[1]); FileInputFormat.setInputPaths(job, in); FileOutputFormat.setOutputPath(job, out); job.setMapperClass(MapClass.class); job.setReducerClass(ReduceClass.class); job.setInputFormatClass(TextInputFormat.class); job.setOutputFormatClass(TextOutputFormat.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); System.exit(job.waitForCompletion(true) ? 0 : 1); return 0; } public static void main(String[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new AnalyseJob(), args); System.exit(res); } }
]]>
]]>Zookeeper的核心概念:
Zookeeper的服务器安装Q?/span>
Zookeeper代码~写Q?/span>
zk = new ZooKeeper(address, 3000, this);
mutex = new Integer(-1);
System.out.println("Finished starting ZK: " + zk);
private CountDownLatch connectedSignal = new CountDownLatch(1);
SyncPrimitive(String address) {
if(zk == null){
try {
System.out.println("Starting ZK:");
zk = new ZooKeeper(address, 3000, this);
mutex = new Integer(-1);
connectedSignal.await(); // {待q接完成
System.out.println("Finished starting ZK: " + zk);
} catch (IOException e) {
System.out.println(e.toString());
zk = null;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//else mutex = new Integer(-1);
}
synchronized public void process(WatchedEvent event) {
// 此处讄在Watch中会在状态变化后触发事g
if (event.getState() == KeeperState.SyncConnected) {
connectedSignal.countDown();// 倒数-1
}
synchronized (mutex) {
//System.out.println("Process: " + event.getType());
mutex.notify();
}
}Zookeeper的应用场景及方式Q?/span>
2. Master选D则是zookeeper中最为经典的使用场景了?/span>
]]>
灰色背景部分Z些介l,或过E中出现问题的描qͼ可以直接忽略?/span>
[root@localhost hadoop-1.0.0]# ./bin/hadoop jar com.suntang.analyse.hadoop-0.0.1.jar com.suntang.analyse.hadoop.AnalyseJob /user/root/news.txt output_root_test
]]>
#!/usr/bin/env bash
for year in all/*
do
echo -ne `basename $year .gz`"\t"
gunzip -c $year | \
awk '{ temp = substr($0, 88, 5) + 0;
q = substr($0, 93, 1);
if (temp !=9999 && q ~ /[01459]/ && temp > max) max = temp }
END { print max }'
done
使用linux脚本打印每年最高温度,先解释一下该脚本几个注意炏V?/span>
脚本目的是发现每q的最高温度,W一?/span>for year in 后的all/*表示在名UCؓall的文件夹下每q度的温度信息都?/span> ?/span> 1990.gz 方式存在。?/span>gunzip方式解压q打华ͼҎ印的内容使用awk函数q行处理Q获取最大温度,单个文g处理完毕后打?/span>max?/span>
在上一中获取的数据包是这Pq度为文件夹Q当中包含若q个温度详情文g?/span>
E:\testData\1990\010010-9999-1990.gz
E:\testData\1990\010014-9999-1990.gz
E:\testData\1990\010015-9999-1990.gz
E:\testData\1990\010016-9999-1990.gz
…
从后?/span>Appendix C的描qC得知Q实际上作者对q样的数据进行了处理Q因?/span>hadoop在处理大量的文件时无法辑ֈ很高的效率,因此作者?/span>hadoop小文g合ƈQƈ且给Z代码?/span>
我比较希望能够用脚本处理,所有的gz解压之后Q合q成Z个文Ӟ打包?/span>gz的格式,q样p完全W合之前那段脚本的处理方式。所以,脚本如下Q?/span>
packyear
#! /bin/sh
# /usr/data/packyear
# unzip all gz files in data
for yeards in data/*
do
# unzip all gz files in year directory
for gzfile in $yeards/*
do
gunzip $gzfile
done
# cat all content to year file
cat $yeards/* | head -2 >> $yeards.tc
# remove year directory
rm -rf $yeards
mv $yeards.tc $yeards
# zip the tc file
gzip $yeards
done
Ҏ实际路径改写的计最大温度的脚本
maxyear
#! /bin/sh
# /usr/data/ maxyear
for year in /usr/data/*
do
basename $year .gz
gunzip -c $year | \
awk '{temp=substr($0, 88, 5)+0;
q=substr($0, 93, 1);
if(temp !=9999 && q ~ /[01459]/ && temp > max) max = temp}
END {print max}'
done
q个脚本最l显C出来会是:
1990
3
q样的格式。由于对数据l构的不熟悉Q所以不定昄出来的数据是否正,但是基本的脚本和数据操作方式是q样了?/span>
For example, here are the first entries for 1990:
% ls raw/1990 | head
010010-99999-1990.gz
010014-99999-1990.gz
010015-99999-1990.gz
010016-99999-1990.gz
010017-99999-1990.gz
010030-99999-1990.gz
010040-99999-1990.gz
010080-99999-1990.gz
010100-99999-1990.gz
010150-99999-1990.gz
对于数据的来源很困惑Q不知道如何下蝲?/span>google之后?/span>http://lucene.472066.n3.nabble.com/The-NCDC-Weather-Data-for-Hadoop-the-Definitive-Guide-td3736774.html q篇帖子中发现方法。现在记录一?/span>
q接http://www.ncdc.noaa.gov/
注意到左边的Free Data?/span>
点击后{到的面向下拉,?/span>Free Data B中友一个完全免费的FTPQ红框所C)
提供ftp地址为:ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/
我用了FileZillaQ?/span>http://dl.pconline.com.cn/html_2/1/89/id=5826&pn=0.htmlQ进行下?/span>
?/span>1w多个文gQ可能是不需要完全下载的?/span>
Q完Q?/span>