第一篇:hadoop學習心得
1.FileInputFormat splits only large files.Here “l(fā)arge” means larger than an HDFS block.The split size is normally the size of an HDFS block, which is appropriate for most applications;however,it is possible to control this value by setting various Hadoop properties.2.So the split size is blockSize.3.Making the minimum split size greater than the block size increases the split size, but at the cost of locality.4.One reason for this is that FileInputFormat generates splits in such a way that each split is all or part of a single file.If the file is very small(“small” means significantly smaller than an HDFS block)and there are a lot of them, then each map task will process very little input, and there will be a lot of them(one per file), each of which imposes extra bookkeeping overhead.hadoop處理大量小數(shù)據(jù)文件效果不好:
hadoop對數(shù)據(jù)的處理是分塊處理的,默認是64M分為一個數(shù)據(jù)塊,如果存在大量小數(shù)據(jù)文件(例如:2-3M一個的文件)這樣的小數(shù)據(jù)文件遠遠不到一個數(shù)據(jù)塊的大小就要按一個數(shù)據(jù)塊來進行處理。
這樣處理帶來的后果由兩個:1.存儲大量小文件占據(jù)存儲空間,致使存儲效率不高檢索速度也比大文件慢。
2.在進行MapReduce運算的時候這樣的小文件消費計算能力,默認是按塊來分配Map任務的(這個應該是使用小文件的主要缺點)
那么如何解決這個問題呢?
1.使用Hadoop提供的Har文件,Hadoop命令手冊中有可以對小文件進行歸檔。2.自己對數(shù)據(jù)進行處理,把若干小文件存儲成超過64M的大文件。
FileInputFormat is the base class for all implementations of InputFormat that use files as their data source(see Figure 7-2).It provides two things: a place to define which files are included as the input to a job, and an implementation for generating splits for the input files.The job of dividing splits into records is performed by subclasses.An InputSplit has a length in bytes, and a set of storage locations, which are just hostname strings.Notice that a split doesn’t contain the input data;it is just a reference to the data.As a MapReduce application writer, you don’t need to deal with InputSplits directly, as they are created by an InputFormat.An InputFormat is responsible for creating the input splits, and dividing them into records.Before we see some concrete examples of InputFormat, let’s briefly examine how it is used in MapReduce.Here’s the interface:
public interface InputFormat
The JobClient calls the getSplits()method.On a tasktracker, the map task passes the split to the getRecordReader()method on InputFormat to obtain a RecordReader for that split.A related requirement that sometimes crops up is for mappers to have access to the full contents of a file.Not splitting the file gets you part of the way there, but you also need to have a RecordReader that delivers the file contents as the value of the record.One reason for this is that FileInputFormat generates splits in such a way that each split is all or part of a single file.If the file is very small(“small” means significantly smaller than an HDFS block)and there are a lot of them, then each map task will process very little input, and there will be a lot of them(one per file), each of which imposes extra bookkeeping overhead.Example 7-2.An InputFormat for reading a whole file as a record public class WholeFileInputFormat extends FileInputFormat
Input splits are represented by the Java interface, InputSplit(which, like all of the classes mentioned in this section, is in the org.apache.hadoop.mapred package?): public interface InputSplit extends Writable { long getLength()throws IOException;String[] getLocations()throws IOException;}
An InputSplit has a length in bytes, and a set of storage locations, which are just hostname strings.Notice that a split doesn’t contain the input data;it is just a reference to the data.The storage locations are used by the MapReduce system to place map tasks as close to the split’s data as possible, and the size is used to order the splits so that the largest get processed first, in an attempt to minimize the job runtime(this is an instance of a greedy approximation algorithm).As a MapReduce application writer, you don’t need to deal with InputSplits directly, as they are created by an InputFormat.An InputFormat is responsible for creating the input splits, and dividing them into records.Before we see some concrete examples of InputFormat, let’s briefly examine how it is used in MapReduce.Here’s the interface:
public interface InputFormat
Having calculated the splits, the client sends them to the jobtracker, which uses their storage locations to schedule map tasks to process them on the tasktrackers.A path may represent a file, a directory, or, by using a glob, a collection of files and directories.A path representing a directory includes all the files in the directory as input to the job.See “File patterns” on page 60 for more on using globs.It is a common requirement to process sets of files in a single operation.For example, a MapReduce job for log processing might analyze a month worth of files, contained in a number of directories.Rather than having to enumerate each file and directory to specify the input, it is convenient to use wildcard characters to match multiple files with a single expression, an operation that is known as globbing.Hadoop provides two FileSystem methods for processing globs: public FileStatus[] globStatus(Path pathPattern)throws IOException public FileStatus[] globStatus(Path pathPattern, PathFilter filter)throws IOException
第二篇:Hadoop之JobTrack分析
Hadoop之JobTrack分析
1.client端指定Job的各種參數(shù)配置之后調(diào)用job.waitForCompletion(true)方法提交Job給JobTracker,等待Job 完成。
[java] view plaincopyprint?
1.public void submit()throws IOException, InterruptedException, 2.ClassNotFoundException { 3.ensureState(JobState.DEFINE);//檢查JobState狀態(tài)
4.setUseNewAPI();//檢查及設置是否使用新的MapReduce API
5.6.// Connect to the JobTracker and submit the job
7.connect();//鏈接JobTracker
8.info = jobClient.submitJobInternal(conf);//將job信息提交
9.super.setJobID(info.getID());
10.state = JobState.RUNNING;//更改job狀態(tài)
11.}
以上代碼主要有兩步驟,連接JobTracker并提交Job信息。connect方法主要是實例化JobClient對象,包括設置JobConf和init工作:
[java] view plaincopyprint?
1.public void init(JobConf conf)throws IOException {
2.String tracker = conf.get(“mapred.job.tracker”, “l(fā)ocal”);//讀取配置文件信息用于判斷該Job是運行于本地單機模式還是分布式模式
3.tasklogtimeout = conf.getInt(4.TASKLOG_PULL_TIMEOUT_KEY, DEFAULT_TASKLOG_TIMEOUT);5.this.ugi = UserGroupInformation.getCurrentUser();
6.if(“l(fā)ocal”.equals(tracker)){//如果是單機模式,new LocalJobRunner
7.conf.setNumMapTasks(1);
8.this.jobSubmitClient = new LocalJobRunner(conf);9.} else {
10.this.jobSubmitClient = createRPCProxy(JobTracker.getAddress(conf), conf);
11.} 12.}
分布式模式下就會創(chuàng)建一個RPC代理鏈接:
[java] view plaincopyprint?
1.public static VersionedProtocol getProxy(2.Class extends VersionedProtocol> protocol,3.long clientVersion, InetSocketAddress addr, UserGroupInformation ticket,4.Configuration conf, SocketFactory factory, int rpcTimeout)throws IOException { 5.6.if(UserGroupInformation.isSecurityEnabled()){ 7.SaslRpcServer.init(conf);8.}
9.VersionedProtocol proxy =
10.(VersionedProtocol)Proxy.newProxyInstance(11.protocol.getClassLoader(), new Class[] { protocol },12.new Invoker(protocol, addr, ticket, conf, factory, rpcTimeout));
13.long serverVersion = proxy.getProtocolVersion(protocol.getName(), 14.clientVersion);15.if(serverVersion == clientVersion){ 16.return proxy;17.} else {
18.throw new VersionMismatch(protocol.getName(), clientVersion, 19.serverVersion);20.} 21.}
從上述代碼可以看出hadoop實際上使用了Java自帶的Proxy API來實現(xiàn)Remote Procedure Call 初始完之后,需要提交job [java] view plaincopyprint?
1.info = jobClient.submitJobInternal(conf);//將job信息提交
submit方法做以下幾件事情:
1.將conf中目錄名字替換成hdfs代理的名字
2.檢查output是否合法:比如路徑是否已經(jīng)存在,是否是明確的3.將數(shù)據(jù)分成多個split并放到hdfs上面,寫入job.xml文件
4.調(diào)用JobTracker的submitJob方法
該方法主要新建JobInProgress對象,然后檢查訪問權(quán)限和系統(tǒng)參數(shù)是否滿足job,最后addJob:
[java] view plaincopyprint?
1.private synchronized JobStatus addJob(JobID jobId, JobInProgress job)2.throws IOException { 3.totalSubmissions++;4.5.synchronized(jobs){
6.synchronized(taskScheduler){
7.jobs.put(job.getProfile().getJobID(), job);
8.for(JobInProgressListener listener : jobInProgressListeners){ 9.listener.jobAdded(job);10.} 11.} 12.}
13.myInstrumentation.submitJob(job.getJobConf(), jobId);14.job.getQueueMetrics().submitJob(job.getJobConf(), jobId);15.16.LOG.info(“Job ” + jobId + “ added successfully for user '”
17.+ job.getJobConf().getUser()+ “' to queue '”
18.+ job.getJobConf().getQueueName()+ “'”);19.AuditLogger.logSuccess(job.getUser(),20.Operation.SUBMIT_JOB.name(), jobId.toString());21.return job.getStatus();22.}
totalSubmissions記錄client端提交job到JobTracker的次數(shù)。而jobs則是JobTracker所有可以管理的job的映射表
Map
hadoop job調(diào)度機制; public enum SchedulingMode { FAIR, FIFO } 1.公平調(diào)度FairScheduler 對于每個用戶而言,分布式資源是公平分配的,每個用戶都有一個job池,假若某個用戶目前所占有的資源很多,對于其他用戶而言是不公平的,那么調(diào)度器就會殺掉占有資源多的用戶的一些task,釋放資源供他人使用 2.容量調(diào)度JobQueueTaskScheduler 在分布式系統(tǒng)上維護多個隊列,每個隊列都有一定的容量,每個隊列中的job按照FIFO的策略進行調(diào)度。隊列中可以包含隊列。
兩個Scheduler都要實現(xiàn)TaskScheduler的public synchronized List
接下來看看JobTracker的工作: 記錄更新JobTracker重試的次數(shù):
[java] view plaincopyprint?
1.while(true){ 2.try {
3.recoveryManager.updateRestartCount();4.break;
5.} catch(IOException ioe){
6.LOG.warn(“Failed to initialize recovery manager.”, ioe);7.// wait for some time
8.Thread.sleep(FS_ACCESS_RETRY_PERIOD);9.LOG.warn(“Retrying...”);10.} 11.}
啟動Job調(diào)度器,默認是FairScheduler: taskScheduler.start();主要是初始化一些管理對象,比如job pool管理池
[java] view plaincopyprint?
1.// Initialize other pieces of the scheduler
2.jobInitializer = new JobInitializer(conf, taskTrackerManager);3.taskTrackerManager.addJobInProgressListener(jobListener);4.poolMgr = new PoolManager(this);5.poolMgr.initialize();
6.loadMgr =(LoadManager)ReflectionUtils.newInstance(7.conf.getClass(“mapred.fairscheduler.loadmanager”, 8.CapBasedLoadManager.class, LoadManager.class), conf);9.loadMgr.setTaskTrackerManager(taskTrackerManager);10.loadMgr.setEventLog(eventLog);11.loadMgr.start();
12.taskSelector =(TaskSelector)ReflectionUtils.newInstance(13.conf.getClass(“mapred.fairscheduler.taskselector”, 14.DefaultTaskSelector.class, TaskSelector.class), conf);15.taskSelector.setTaskTrackerManager(taskTrackerManager);16.taskSelector.start();
[java] view plaincopyprint?
1.JobInitializer有一個確定大小的ExecutorService threadPool,每個thread用于初始化job
[java] view plaincopyprint?
1.try {
2.JobStatus prevStatus =(JobStatus)job.getStatus().clone();3.LOG.info(“Initializing ” + job.getJobID());4.job.initTasks();
5.// Inform the listeners if the job state has changed 6.// Note : that the job will be in PREP state.7.JobStatus newStatus =(JobStatus)job.getStatus().clone();8.if(prevStatus.getRunState()!= newStatus.getRunState()){ 9.JobStatusChangeEvent event =
10.new JobStatusChangeEvent(job, EventType.RUN_STATE_CHANGED, prevStatus,11.newStatus);
12.synchronized(JobTracker.this){ 13.updateJobInProgressListeners(event);14.} 15.} 16.}
初始化操作主要用于初始化生成tasks然后通知其他的監(jiān)聽者執(zhí)行其他操作。initTasks主要處理以下工作:
[java] view plaincopyprint?
1.// 記錄用戶提交的運行的job信息
2.try {
3.userUGI.doAs(new PrivilegedExceptionAction
5.public Object run()throws Exception {
6.JobHistory.JobInfo.logSubmitted(getJobID(), conf, jobFile, 7.startTimeFinal, hasRestarted());8.return null;9.} 10.});
11.} catch(InterruptedException ie){ 12.throw new IOException(ie);13.} 14.15.// 設置并記錄job的優(yōu)先級
16.setPriority(this.priority);17.18.//
19.//生成每個Task需要的密鑰
20.//
21.generateAndStoreTokens();22.然后讀取JobTracker split的數(shù)據(jù)的元信息,元信息包括以下屬性信息:
[java] view plaincopyprint?
1.private TaskSplitIndex splitIndex;//洗牌后的索引位置
2.private long inputDataLength;//洗牌后數(shù)據(jù)長度 3.private String[] locations;//數(shù)據(jù)存儲位置
然后根據(jù)元信息的長度來計算numMapTasks并校驗數(shù)據(jù)存儲地址是否可以連接 接下來生成map tasks和reducer tasks:
[java] view plaincopyprint?
1.maps = new TaskInProgress[numMapTasks];2.for(int i=0;i < numMapTasks;++i){
3.inputLength += splits[i].getInputDataLength();4.maps[i] = new TaskInProgress(jobId, jobFile, 5.splits[i],6.jobtracker, conf, this, i, numSlotsPerMap);
7.}
[java] view plaincopyprint?
1.this.jobFile = jobFile;2.this.splitInfo = split;3.this.jobtracker = jobtracker;4.this.job = job;5.this.conf = conf;
6.this.partition = partition;
7.this.maxSkipRecords = SkipBadRecords.getMapperMaxSkipRecords(conf);8.this.numSlotsRequired = numSlotsRequired;9.setMaxTaskAttempts();10.init(jobid);
以上除了task對應的jobTracker,split信息和job信息外,還設置了
[java] view plaincopyprint?
1.maxSkipRecords---記錄task執(zhí)行的時候最大可以跳過的錯誤記錄數(shù);
2.
setMaxTaskAttempts--設置task最多可以執(zhí)行的次數(shù)。當一個task執(zhí)行兩次都失敗了之后,會以skip mode模式再重新執(zhí)行一次,記錄那些bad record,3.然后第四次再執(zhí)行的時候,跳過這些bad records 4.
5.新建reducer task的過程也很類似。
6.7.
8.
10.
12.
14.
第三篇:Hadoop常見錯誤總結(jié)
Hadoop常見錯誤總結(jié) 2010-12-30 13:55 錯誤1:bin/hadoop dfs 不能正常啟動,持續(xù)提示:
INFO ipc.Client: Retrying connect to server: localhost/127.0.0.1:9000.Already tried 0 time(s).原因:由于 dfs 的部分文件默認保存在tmp文件夾,在系統(tǒng)重啟時被刪除。解決:修改core-site.xml 的 hadoop.tmp.dir配置文件路徑:/home/hadoop/tmp。
錯誤2:hadoop出現(xiàn)了一些問題。用$ bin/hadoop dfsadmin-report 測試的時候,發(fā)現(xiàn)dfs沒有加載。顯示如下:
Configured Capacity: 0(0 KB)Present Capacity: 0(0 KB)DFS Remaining: 0(0 KB)DFS Used: 0(0 KB)DFS Used%: ?% Under replicated blocks: 0 Blocks with corrupt replicas: 0 Missing blocks: 0 查看日志:
ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: java.io.IOException: Incompatible namespaceIDs in /home/hadoop/data: namenode namespaceID = 2033006627;datanode namespaceID = 1589898341 經(jīng)分析,是由于namenode namespaceID = 2033006627;和datanode namespaceID = 1589898341 不一致造成原因。
修改了namenode namespaceID = 1589898341 可以使用,但是重啟之后,又不可以用了。
最后解決方案:刪除hadoop用戶下的name文件夾,data文件夾,tmp文件夾,temp文件里的內(nèi)容,然后重新執(zhí)行namenode命令。重啟電腦之后,正常。
錯誤3:File /home/hadoop/tmp/mapred/system/jobtracker.info could only be replicated to 0 nodes, instead of 1 出現(xiàn)此錯誤,一般發(fā)生在datanode與namenode還沒有進行連接,就開始往hdfs系統(tǒng)上put數(shù)據(jù)了。稍等待一會,就可以了。
也可以使用:hadoop dfsadmin –report命令查看集群的狀態(tài)。錯誤4:
每次啟動總有部分datanade不能去全部啟動,查看日志文件,顯示為: ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: java.net.UnknownHostException: zgchen-ubutun: zgchen-ubutun at java.net.InetAddress.getLocalHost(InetAddress.java:1426)。分析:這是由于datanode 找不到服務host引起的。
解決:通過查找/etc/hostname 找到hostname;比如:ubuntu。然后找到/etc/hosts,添加:127.0.1.1 ubuntu 錯誤5:
java.lang.OutOfMemoryError: GC overhead limit exceeded 分析:這個是JDK6新添的錯誤類型。是發(fā)生在GC占用大量時間為釋放很小空間的時候發(fā)生的,是一種保護機制。解決方案是,關閉該功能,可以添加JVM的啟動參數(shù)來限制使用內(nèi)存:-XX:-UseGCOverheadLimit 添加位置是:mapred-site.xml 里新增項:mapred.child.java.opts 內(nèi)容:-XX:-UseGCOverheadLimit java.lang.OutOfMemoryError: Java heap space 出現(xiàn)這種異常,明顯是jvm內(nèi)存不夠得原因,要修改所有的datanode的jvm內(nèi)存大小。
Java-Xms1024m-Xmx4096m 一般jvm的最大內(nèi)存使用應該為總內(nèi)存大小的一半,我們使用的8G內(nèi)存,所以設置為4096m,這一值可能依舊不是最優(yōu)的值。(其實對于最好設置為真實物理內(nèi)存大小的0.8)
錯誤6:Too many fetch-failures Answer: 出現(xiàn)這個問題主要是結(jié)點間的連通不夠全面。1)檢查、/etc/hosts 要求本機ip 對應 服務器名
要求要包含所有的服務器ip + 服務器名 2)檢查.ssh/authorized_keys 要求包含所有服務器(包括其自身)的public key 錯誤7:處理速度特別的慢 出現(xiàn)map很快 但是reduce很慢 而且反復出現(xiàn) reduce=0% Answer: 結(jié)合第二點,然后修改可用內(nèi)存大小。
conf/hadoop-env.sh 中的export HADOOP_HEAPSIZE=4000 錯誤8:能夠啟動datanode,但無法訪問,也無法結(jié)束的錯誤
在重新格式化一個新的分布式文件時,需要將你NameNode上所配置的dfs.name.dir這一namenode用來存放NameNode 持久存儲名字空間及事務日志的本地文件系統(tǒng)路徑刪除,同時將各DataNode上的dfs.data.dir的路徑 DataNode 存放塊數(shù)據(jù)的本地文件系統(tǒng)路徑的目錄也刪除。如本此配置就是在NameNode上刪除/home/hadoop/NameData,在DataNode上刪除/home/hadoop/DataNode1和/home/hadoop/DataNode2。這是因為Hadoop在格式化一個新的分布式文件系統(tǒng)時,每個存儲的名字空間都對應了建立時間的那個版本(可以查看/home/hadoop /NameData/current目錄下的VERSION文件,上面記錄了版本信息),在重新格式化新的分布式系統(tǒng)文件時,最好先刪除NameData 目錄。必須刪除各DataNode的dfs.data.dir。這樣才可以使namedode和datanode記錄的信息版本對應。
注意:刪除是個很危險的動作,不能確認的情況下不能刪除!做好刪除的文件等通通備份!
錯誤9:java.io.IOException: Could not obtain block: blk_***469_1100 file=/user/hive/warehouse/src_20100924_log/src_20100924_log 出現(xiàn)這種情況大多是結(jié)點斷了,沒有連接上。或者
mapred.tasktracker.map.tasks.maximum 的設置 超過 cpu cores數(shù)目,導致出現(xiàn)獲取不到文件。
錯誤10:Task Id : attempt_201010291615_0001_m_000234_0, Status : FAILED Error: java.io.IOException: No space left on device Task Id : attempt_201010291615_0001_m_000240_0, Status : FAILED java.io.IOException: Spill failed 磁盤空間不夠,應該分析磁盤空間df-h 檢查是否還存在磁盤空間。錯誤11:Task Id : attempt_201011011336_0007_m_000001_0, Status : FAILED org.apache.hadoop.hbase.client.RegionOfflineException: region offline: lm,1288597709144 網(wǎng)上說,將/hbase刪除;重啟hbase后,可以正常應用了。但是我找不到/hbase目錄,只好自己重新刪除掉一些hadoop文件,重新生成文件管理系統(tǒng)。
還有一個可能是,配置錯了/hbase/conf/hbase-env.sh的HBASE_CLASSPATH,這個默認是不配置的,所以可以不配置。
錯誤12:org.apache.hadoop.hbase.TableNotFoundException: org.apache.hadoop.hbase.TableNotFoundException: lm 找不到表,hbase啟動了,檢查一下是否存在需要的Htable。
第四篇:Hadoop運維工程師崗位職責簡潔版
Hadoop運維工程師崗位職責簡潔版
1.負責Hadoop相關項目日常運行維護、故障排查工作;
2.負責Hadoop集群的監(jiān)控和配置調(diào)優(yōu)工作;
3.負責Hadoop平臺的用戶管理、權(quán)限分配、資源分配;
4.負責集群服務器軟件的安裝、維護、部署、更新;
Hadoop運維工程師崗位職責(二)
1.負責高并發(fā),大存儲和實時流的Hadoop/spark大數(shù)據(jù)平臺規(guī)劃,運維,監(jiān)控和優(yōu)化工作;
2.保證Hadoop/spark平臺各核心服務運行的穩(wěn)定、高效;
___對Hadoop/spark平臺運維不斷優(yōu)化,提升數(shù)據(jù)產(chǎn)品的質(zhì)量和響應速度;
4.開發(fā)各種Hadoop大數(shù)據(jù)自動化運維與監(jiān)控工具;
___平臺大數(shù)據(jù)環(huán)境的部署維護和技術支持;
6.應用故障的處理跟蹤及統(tǒng)計匯總分析;
7.應用安全,數(shù)據(jù)的日常備份和應急恢復。
Hadoop運維工程師崗位職責(三)
1、負責移動大數(shù)據(jù)中心的建設與維護;
2、負責安徽移動hadoop集群的故障排查、解決;
3、其他省份hadoop項目建設提供技術支持。
Hadoop運維工程師崗位職責(四)
1.負責Hadoop及相關組件的部署和維護,保證其穩(wěn)定運行;
2.開發(fā)和使用Hadoop大數(shù)據(jù)自動化運維與監(jiān)控工具;
3.基于大數(shù)據(jù)應用需求,不斷調(diào)整和優(yōu)化Hadoop框架及組件的配置,提升性能;
4.為數(shù)據(jù)倉庫、數(shù)據(jù)挖掘建模等數(shù)據(jù)應用項目提供運行環(huán)境支持;
Hadoop運維工程師崗位職責(五)
1.hadoop集群運維、監(jiān)控、開發(fā);
2.hadoop生態(tài)圈框架部署、故障處理、異常排查等基本工作;
___對有助于提升集群處理能力、高可用性、擴展性的各種解決方案進行跟蹤和落地;
4.解決海量數(shù)據(jù)不斷增長面臨的挑戰(zhàn),解決業(yè)務需求;
5、對Hadoop集群進行日常管理,保障系統(tǒng)正常運行;
第五篇:在三臺虛擬機上部署多節(jié)點Hadoop
cd /etc/network vi interfaces 進入vi后,編輯 auto eth0 iface eth0 inet static address IP地址 netmask 掩碼 gateway 網(wǎng)關
重啟SSH:
serivce ssh restart 重啟網(wǎng)卡: /etc/init.d/networking restart 取得root權(quán)限:
sudo passwd su 1.硬件環(huán)境
共有3臺機器,均使用的linux系統(tǒng),Java使用的是openjdk-6-jdk sudo apt-get update sudo apt-get install openjdk-6-jdk 修改主機名:
su vi /etc/hostname IP配置如下:
hadoop1:192.168.75.132(NameNode)hadoop2:192.168.75.131(DataNode)hadoop3:192.168.75.133(DataNode)這里有一點需要強調(diào)的就是,務必要確保每臺機器的主機名和IP地址之間能正確解析。一個很簡單的測試辦法就是ping一下主機名,比如在hadoop1上ping hadoop2,如果能ping通就OK!若不能正確解析,可以修改/etc/hosts文件,如果該臺機器作Namenode用,則需要在hosts文件中加上集群中所有機器的IP地址及其對應的主機名;如果該臺機器作Datanode用,則只需要在hosts文件中加上本機IP地址和Namenode機器的IP地址。
以本文為例,hadoop1(NameNode)中的/etc/hosts文件看起來應該是這樣的:
vi /etc/hosts 127.0.0.1 hadoop1 localhost 192.168.75.132 hadoop1 hadoop1 192.168.75.131 hadoop2 hadoop2 192.168.75.133 hadoop3 hadoop3 hadoop2(DataNode)中的/etc/hosts文件看起來就應該是這樣的: 127.0.0.1 hadoop2 localhost 192.168.75.132 hadoop1 hadoop1 192.168.75.131 hadoop2 hadoop2 hadoop3(DataNode)中的/etc/hosts文件看起來就應該是這樣的: 127.0.0.1 hadoop3 localhost 192.168.75.132 hadoop1 hadoop1 192.168.75.133 hadoop3 hadoop3 對于Hadoop來說,在HDFS看來,節(jié)點分為Namenode和Datanode,其中Namenode只有一個,Datanode可以是很多;在MapReduce看來,節(jié)點又分為Jobtracker和Tasktracker,其中Jobtracker只有一個,Tasktracker可以是很多。我是將namenode和jobtracker部署在hadoop1上,hadoop2, hadoop3作為datanode和tasktracker。當然你也可以將namenode,datanode,jobtracker,tasktracker全部部署在一臺機器上。
2.目錄結(jié)構(gòu)
由于Hadoop要求所有機器上hadoop的部署目錄結(jié)構(gòu)要相同,并且都有一個相同的用戶名的帳戶。
addgroup hadoop adduser--ingroup hadoop hadoop 三臺機器上是這樣的:都有一個hadoop的帳戶,主目錄是/home/hadoop。
下載hadoop:
wget http://mirror.bjtu.edu.cn/apache/hadoop/core/stable/hadoop-0.20.203.0rc1.tar.gz 解壓:[hadoop@ hadoop1:~]$tar-zxvf hadoop-0.21.0.tar.gz Hadoop部署目錄結(jié)構(gòu)如下:/home/hadoop/hadoop0.21.0,所有的hadoop版本放在這個目錄中。
將hadoop0.21.0壓縮包解壓至hadoop0.21.0中,為了方便以后升級,建議建立一個鏈接指向要使用的hadoop版本,不妨設為hadoop,[hadoop@ hadoop1:~]$ln-s hadoop-0.21.0 hadoop 這樣一來,所有的配置文件都在/home/hadoop/hadoop/conf/目錄中,所有執(zhí)行程序都在/home/hadoop/hadoop/bin目錄中。但是由于上述目錄中hadoop的配置文件和hadoop的安裝目錄是放在一起的,這樣一旦日后升級hadoop版本的時候所有的配置文件都會被覆蓋,因此建議將配置文件與安裝目錄分離,一種比較好的方法就是建立一個存放配置文件的目錄,/home/hadoop/hadoop/hadoop-config,然后將/home/hadoop/hadoop/conf/目錄中的masters,slaves,hadoop-env.sh三個文件拷貝到hadoop-config目錄中,并指定環(huán)境變量$HADOOP_CONF_DIR指向該目錄。環(huán)境變量在/home/hadoop/.bashrc和/etc/profile中設定。
如:
HADOOP_CONF_DIR=/home/hadoop/hadoop/hadoop-config export HADOOP_CONF_DIR 即:
cd /home/hadoop/hadoop mkdir hadoop-config cp conf/masters hadoop-config/ cp conf/slaves hadoop-config/ cp conf/hadoop-env.sh hadoop-config/ sudo vi /etc/profile HADOOP_CONF_DIR=/home/hadoop/hadoop/hadoop-config export HADOOP_CONF_DIR vi /home/hadoop/.bashrc HADOOP_CONF_DIR=/home/hadoop/hadoop/hadoop-config export HADOOP_CONF_DIR 綜上所述,為了方便以后升級版本,我們需要做到配置文件與安裝目錄分離,并通過設定一個指向我們要使用的版本的hadoop的鏈接,這樣可以減少我們對配置文件的維護。
3.SSH設置
在Hadoop啟動以后,Namenode是通過SSH(Secure Shell)來啟動和停止各個節(jié)點上的各種守護進程的,這就需要在節(jié)點之間執(zhí)行指令的時候是不需要輸入密碼的方式,故我們需要配置SSH使用無密碼公鑰認證的方式。
首先要保證每臺機器上都裝了SSH服務器,且都正常啟動。實際中我們用的都是OpenSSH,這是SSH協(xié)議的一個免費開源實現(xiàn)。
apt-get install ssh 以本文中的3臺機器為例,現(xiàn)在hadoop1是主節(jié)點,它需要主動發(fā)起SSH連接到hadoop2,對于SSH服務來說,hadoop1就是SSH客戶端,而hadoop2, hadoop3則是SSH服務端,因此在hadoop2,hadoop3上需要確定sshd服務已經(jīng)啟動。簡單的說,在hadoop1上需要生成一個密鑰對,即一個私鑰,一個公鑰。將公鑰拷貝到hadoop2上,這樣,比如當hadoop1向hadoop2發(fā)起ssh連接的時候,hadoop2上就會生成一個隨機數(shù)并用hadoop1的公鑰對這個隨機數(shù)進行加密,并發(fā)送給hadoop1,hadoop1收到這個加密的數(shù)以后用私鑰進行解密,并將解密后的數(shù)發(fā)送回hadoop2,hadoop2確認解密的數(shù)無誤后就允許hadoop1進行連接了。這就完成了一次公鑰認證過程。
對于本文中的3臺機器,首先在hadoop1上生成密鑰對:
[hapoop@hadoop1:~]$ssh-keygen-t dsa –P ‘’ –f ~/.ssh/id_dsa 這個命令將為hadoop1上的用戶hadoop生成其密鑰對。生成的密鑰對id_rsa,id_rsa.pub,在/home/hadoop/.ssh目錄下。
[hapoop@hadoop1:.ssh]$cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys 然后將id_rsa.pub的內(nèi)容復制/home/hadoop/.ssh/authorized_keys文件中。
對于hadoop2:[hapoop @ hadoop2:~]$mkdir.ssh 對于hadoop3:[hapoop @ hadoop3:~]$mkdir.ssh [hapoop @ hapoop1:.ssh]$scp authorized_keys hapoop2:/home/hapoop/.ssh/ [hapoop @ hapoop1:.ssh]$scp authorized_keys hapoop3:/home/hapoop/.ssh/
此處的scp就是通過ssh進行遠程copy,此處需要輸入遠程主機的密碼,即hadoop2,hadoop3機器上hadoop帳戶的密碼,當然,你也可以用其他方法將authorized_keys文件拷貝到其他機器上。
[hadoop@hadoop2:.ssh]$chmod 640 authorized_keys [hadoop@hadoop3:.ssh]$chmod 640 authorized_keys
這一步非常關鍵,必須保證authorized_keys只對其所有者有讀寫權(quán)限,其他人不允許有寫的權(quán)限,否則SSH是不會工作的。
[hadoop@ hadoop2:.ssh] $ls-la
drwx------2 hadoop hadoop.drwx------3 hadoop hadoop..-rw-r--r--1 hadoop hadoop authorized_keys
注意每個機器上的.ssh目錄的ls-la都應該和上面是一樣的
接著,在3臺機器上都需要對sshd服務進行配置,修改文件/etc/ssh/sshd_config。
vi /etc/ssh/sshd_config #去除密碼認證
PasswordAuthentication no
(?如果這樣,putty就不能登陸Linux了,去掉)AuthorizedKeysFile.ssh/authorized_keys 至此各個機器上的SSH配置已經(jīng)完成,可以測試一下了,比如hadoop1向hadoop2發(fā)起ssh連接。
[hadoop@hadoop1:~]$ssh hadoop2 如果ssh配置好了,就會出現(xiàn)以下提示信息 The authenticity of host [hadoop2] can't be established.Key fingerprint is 1024 5f:a0:0b:65:d3:82:df:ab:44:62:6d:98:9c:fe:e9:52.Are you sure you want to continue connecting(yes/no)? OpenSSH告訴你它不知道這臺主機,但是你不用擔心這個問題,因為你是第一次登錄這臺主機。鍵入“yes”。這將把這臺主機的“識別標記”加到“~/.ssh/know_hosts”文件中。第二次訪問這臺主機的時候就不會再顯示這條提示信息了。
然后你會發(fā)現(xiàn)不需要輸入密碼就可以建立ssh連接了,恭喜你,配置成功了,不過,別忘了測試本機ssh hadoop1。
(應該是只設置hadoop1對hadoop2發(fā)送ssh連接和hadoop1對hadoop3發(fā)送ssh連接,下面的需要配置嗎?)同樣,hadoop1對hadoop3發(fā)起ssh連接,再在hadoop3發(fā)起對hadoop1的連接。這里不在贅述。
4.Hadoop環(huán)境變量
在/home/hadoop/hadoop/hadoop-config目錄下的hadoop-env.sh中設置Hadoop需要的環(huán)境變量,其中JAVA_HOME是必須設定的變量。HADOOP_HOME變量可以設定也可以不設定,如果不設定,HADOOP_HOME默認的是bin目錄的父目錄,即本文中的/home/hadoop/hadoop。我的是這樣設置的: export HADOOP_HOME=/home/hadoop/hadoop 這一句話export JAVA_HOME=/usr/java/jdk1.6.0_20改成: export JAVA_HOME=/usr/lib/jvm/java-6-openjdk 5.Hadoop配置文件
修改slaves文件
如前所述,在hadoop1(NameNode)的hadoop-config/目錄下,打開slaves文件,該文件用來指定所有的DataNode,一行指定一個主機名。即本文中的hadoop2、hadoop3,因此slaves文件看起來應該是這樣的:
括號?????? 即hadoop2和192.168.75.131二者寫一個就行 hadoop2(192.168.75.131)hadoop3(192.168.75.133)修改masters文件
打開masters文件,該文件用來指定NameNode,內(nèi)容如下: hadoop1(192.168.75.132)
在hadoop的安裝目錄分別找到core-default.xml,hdfs-default.xml,mapred-default.xml三個文件,然后copy到hadoop-config/目錄下,這三個文件包含Hadoop的所有配置項,然后把這個分別改名為core-site.xml,hdfs-site.xml,mapred-site.xml,我們根據(jù)需要修改如下:(注意:下面的配置文件中不要有中文或中文的符號,否則報錯)修改core-site.xml core-site.xml的修改項如下:
[hadoop@hadoop1:~]$scp-r /home/hadoop/hadoop hadoop2:/home/hadoop/ [hadoop@hadoop1:~]$scp-r /home/hadoop/hadoop hadoop3:/home/hadoop/
至此,可以說,Hadoop已經(jīng)在各個機器上部署完畢了,下面就讓我們開始啟動Hadoop吧。
7.啟動Hadoop 啟動之前,我們先要格式化namenode,先進入~/hadoop/目錄,執(zhí)行下面的命令:
[hadoop@hadoop1 hadoop]$bin/hadoop namenode –format 不出意外,應該會提示格式化成功。如果不成功,就去hadoop/logs/目錄下去查看日志文件。
下面就該正式啟動hadoop啦,在bin/下面有很多啟動腳本,可以根據(jù)自己的需要來啟動。
* start-all.sh 啟動所有的Hadoop守護。包括namenode, datanode, jobtracker, tasktrack * stop-all.sh 停止所有的Hadoop * start-mapred.sh 啟動Map/Reduce守護。包括Jobtracker和Tasktrack * stop-mapred.sh 停止Map/Reduce守護
* start-dfs.sh 啟動Hadoop DFS守護.Namenode和Datanode * stop-dfs.sh 停止DFS守護
在這里,簡單啟動所有守護:
[hadoop@hadoop1:hadoop]$bin/start-all.sh 同樣,如果要停止hadoop,則
[hadoop@hadoop1:hadoop]$bin/stop-all.sh 8.HDFS操作
運行bin/目錄的hadoop命令,可以查看Haoop所有支持的操作及其用法,這里以幾個簡單的操作為例。建立目錄:
[hadoop@hadoop1 hadoop]$bin/hadoop dfs-mkdir testdir 在HDFS中建立一個名為testdir的目錄,復制文件:
[hadoop@hadoop1 hadoop]$bin/hadoop dfs-put /home/large.zip testfile.zip 把本地文件large.zip拷貝到HDFS的根目錄/user/hadoop/下,文件名為testfile.zip,查看現(xiàn)有文件:
[hadoop@hadoop1 hadoop]$bin/hadoop dfs-ls 1 多機模式部署
一、Jdk安裝 命令:
sudo apt-get update sudo apt-get install openjdk-6-jdk 目錄:/usr/lib/jvm/java-6-openjdk 配置環(huán)境變量:
sudo gedit /etc/environment 在其中添加如下兩行:
CLASSPATH=./:/usr/lib/jvm/java-6-openjdk/lib JAVA_HOME=/usr/lib/jvm/java-6-openjdk PATH添加::/usr/lib/jvm/java-6-openjdk
二、新增hadoop用戶
命令:sudo addgroup hadoop sudo adduser--ingroup hadoop hadoop sudo gedit etc/sudoers 添加配置:
在root ALL=(ALL)ALL后 hadoop ALL=(ALL)ALL使hadoop用戶具有root權(quán)限(id:查看用戶)
三、ssh配置
用hadoop賬戶進行登錄。
安裝openssh-server:sudo apt-get install openssh-server 建立SSH KEY:ssh-keygen-t rsa-P “" 啟用SSH KEY:cat $HOME/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys sudo /etc/init.d/ssh reload 驗證SSH的配置:ssh localhost
四、安裝hadoop并更改用戶所有權(quán)
wget http://mirror.bjtu.edu.cn/apache/hadoop/core/stable/hadoop-0.20.203.0rc1.tar.gz 我們采用的Hadoop版本是最新的Hadoop-0.20.2,可到Apache基金會官方主頁下載http://004km.cn/dyn/closer.cgi/hadoop/core,然后使用tar或直接解壓到/home/hadoop下,解壓后得到一個hadoop-0.20.2的一個文件夾。
安裝目錄:/usr/local/hadoop
更改所有權(quán):chown-R hadoop:hadoop hadoop
五、配置hadoop(1)配置$HADOOP_HOME/conf/hadoop-env.sh 切換到Hadoop的安裝路徑找到hadoop-0.20.2下的conf/hadoop-env.sh文件 將:# export JAVA_HOME=/usr/lib/j2sdk1.5-sun 改為:export JAVA_HOME=/usr/lib/jvm/java-6-openjdk(2)配置$HADOOP_HOME/conf/core-site.xml 切換到Hadoop的安裝路徑找到hadoop-0.20.2下的conf/core-site.xml文件 Number of minutes between trash checkpoints.If zero, the trash feature is disabled --NameNode HTTP狀態(tài)監(jiān)視地址 --SecondaryNameNode HTTP狀態(tài)監(jiān)視地址 --每個job的map任務數(shù) --每一個tasktracker同時運行的map任務數(shù)為2 --每一個tasktracker同時運行的reduce任務數(shù)為4
六、格式化namenode 命令:bin/hadoop namenode-format
七、啟動及驗證
命令:./bin/start-all.sh 驗證方法1:jps 驗證方法2:bin/hadoop dfsadmin-report
八:運行Wordcount 1.準備工作
準備兩個文本文件并拷貝到dfs里,具體命令操作如下: $ echo ”hello hadoop world.“ > /tmp/test_file1.txt $ echo ”hello world hadoop.i'm ceshiuser." > /tmp/test_file2.txt $ bin/hadoop dfs-mkdir test-in $ bin/hadoop dfs-copyFromLocal /tmp/test*.txt test-in--$ bin/hadoop dfs-put /tmp/test*.txt test-in--$ bin/hadoop dfs-copyToLocal test-out /tmp/test*.txt--$ bin/hadoop dfs-get test-out /tmp/test*.txt $ bin/hadoop dfs-ls test-in 2.運行
$ bin/hadoop jar hadoop-0.20.2-examples.jar wordcount test-in test-out--% ln-s /home/hadoop/junyu-hadoop/hadoop-iflytek-tempcount.jar tempcount 3.查看結(jié)果
$ bin/hadoop dfs-ls test-out $ bin/hadoop dfs-cat test-out/part-r-00000 分布式部署:
一,修改/etc/hosts文件: 192.168.71.89 node0 192.168.77.213 node1
二,ssh配置
(1)使用scp 命令把生成的公鑰傳給其它服務器,并保存成不同的名字,如192.168.71.89-> 192.168.77.213,并且保存為89_id_rsa.pub 的時候命令如下:
scp id_rsa.pub hadoop@192.168.77.213:/home/hadoop/.ssh/89_id_rsa.pub(2)登錄192.168.77.213,可以遠程登錄:ssh hadoop@192.168.77.213,進入當前用戶默認目錄下的.ssh 目錄:cd ~/.ssh
(3)把公鑰內(nèi)容添加到登錄認證文件中:cat 89_id_rsa.pub >> authorized_keys
(4)登錄到192.168.71.89 主機,使用ssh hadoop@192.168.77.213 進行連接213 主機,這時候會出現(xiàn)輸入yes/no? 的提示,輸入yes。
三,配置hadoop文件。目錄:/usr/local/hadoop/conf/ conf/masters :192.168.71.89 conf/slaves :192.168.77.213
修改 core-site.xml 文件
修改 hdfs-site.xml 文件
1:
修改mapred-site.xml文件