第一篇:hadoop學習心得
1.FileInputFormat splits only large files.Here “large” 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處理大量小數據文件效果不好:
hadoop對數據的處理是分塊處理的,默認是64M分為一個數據塊,如果存在大量小數據文件(例如:2-3M一個的文件)這樣的小數據文件遠遠不到一個數據塊的大小就要按一個數據塊來進行處理。
這樣處理帶來的后果由兩個:1.存儲大量小文件占據存儲空間,致使存儲效率不高檢索速度也比大文件慢。
2.在進行MapReduce運算的時候這樣的小文件消費計算能力,默認是按塊來分配Map任務的(這個應該是使用小文件的主要缺點)
那么如何解決這個問題呢?
1.使用Hadoop提供的Har文件,Hadoop命令手冊中有可以對小文件進行歸檔。2.自己對數據進行處理,把若干小文件存儲成超過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的各種參數配置之后調用job.waitForCompletion(true)方法提交Job給JobTracker,等待Job 完成。
[java] view plaincopyprint?
1.public void submit()throws IOException, InterruptedException, 2.ClassNotFoundException { 3.ensureState(JobState.DEFINE);//檢查JobState狀態
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狀態
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”, “local”);//讀取配置文件信息用于判斷該Job是運行于本地單機模式還是分布式模式
3.tasklogtimeout = conf.getInt(4.TASKLOG_PULL_TIMEOUT_KEY, DEFAULT_TASKLOG_TIMEOUT);5.this.ugi = UserGroupInformation.getCurrentUser();
6.if(“local”.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.}
分布式模式下就會創建一個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來實現Remote Procedure Call 初始完之后,需要提交job [java] view plaincopyprint?
1.info = jobClient.submitJobInternal(conf);//將job信息提交
submit方法做以下幾件事情:
1.將conf中目錄名字替換成hdfs代理的名字
2.檢查output是否合法:比如路徑是否已經存在,是否是明確的3.將數據分成多個split并放到hdfs上面,寫入job.xml文件
4.調用JobTracker的submitJob方法
該方法主要新建JobInProgress對象,然后檢查訪問權限和系統參數是否滿足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的次數。而jobs則是JobTracker所有可以管理的job的映射表
Map
hadoop job調度機制; public enum SchedulingMode { FAIR, FIFO } 1.公平調度FairScheduler 對于每個用戶而言,分布式資源是公平分配的,每個用戶都有一個job池,假若某個用戶目前所占有的資源很多,對于其他用戶而言是不公平的,那么調度器就會殺掉占有資源多的用戶的一些task,釋放資源供他人使用 2.容量調度JobQueueTaskScheduler 在分布式系統上維護多個隊列,每個隊列都有一定的容量,每個隊列中的job按照FIFO的策略進行調度。隊列中可以包含隊列。
兩個Scheduler都要實現TaskScheduler的public synchronized List
接下來看看JobTracker的工作: 記錄更新JobTracker重試的次數:
[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調度器,默認是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然后通知其他的監聽者執行其他操作。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的優先級
16.setPriority(this.priority);17.18.//
19.//生成每個Task需要的密鑰
20.//
21.generateAndStoreTokens();22.然后讀取JobTracker split的數據的元信息,元信息包括以下屬性信息:
[java] view plaincopyprint?
1.private TaskSplitIndex splitIndex;//洗牌后的索引位置
2.private long inputDataLength;//洗牌后數據長度 3.private String[] locations;//數據存儲位置
然后根據元信息的長度來計算numMapTasks并校驗數據存儲地址是否可以連接 接下來生成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執行的時候最大可以跳過的錯誤記錄數;
2.
setMaxTaskAttempts--設置task最多可以執行的次數。當一個task執行兩次都失敗了之后,會以skip mode模式再重新執行一次,記錄那些bad record,3.然后第四次再執行的時候,跳過這些bad records 4.
5.新建reducer task的過程也很類似。
6.7.
8.
10.
12.
14.
第三篇:Hadoop常見錯誤總結
Hadoop常見錯誤總結 2010-12-30 13:55 錯誤1:bin/hadoop dfs 不能正常啟動,持續提示:
INFO ipc.Client: Retrying connect to server: localhost/127.0.0.1:9000.Already tried 0 time(s).原因:由于 dfs 的部分文件默認保存在tmp文件夾,在系統重啟時被刪除。解決:修改core-site.xml 的 hadoop.tmp.dir配置文件路徑:/home/hadoop/tmp。
錯誤2:hadoop出現了一些問題。用$ bin/hadoop dfsadmin-report 測試的時候,發現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 經分析,是由于namenode namespaceID = 2033006627;和datanode namespaceID = 1589898341 不一致造成原因。
修改了namenode namespaceID = 1589898341 可以使用,但是重啟之后,又不可以用了。
最后解決方案:刪除hadoop用戶下的name文件夾,data文件夾,tmp文件夾,temp文件里的內容,然后重新執行namenode命令。重啟電腦之后,正常。
錯誤3:File /home/hadoop/tmp/mapred/system/jobtracker.info could only be replicated to 0 nodes, instead of 1 出現此錯誤,一般發生在datanode與namenode還沒有進行連接,就開始往hdfs系統上put數據了。稍等待一會,就可以了。
也可以使用:hadoop dfsadmin –report命令查看集群的狀態。錯誤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新添的錯誤類型。是發生在GC占用大量時間為釋放很小空間的時候發生的,是一種保護機制。解決方案是,關閉該功能,可以添加JVM的啟動參數來限制使用內存:-XX:-UseGCOverheadLimit 添加位置是:mapred-site.xml 里新增項:mapred.child.java.opts 內容:-XX:-UseGCOverheadLimit java.lang.OutOfMemoryError: Java heap space 出現這種異常,明顯是jvm內存不夠得原因,要修改所有的datanode的jvm內存大小。
Java-Xms1024m-Xmx4096m 一般jvm的最大內存使用應該為總內存大小的一半,我們使用的8G內存,所以設置為4096m,這一值可能依舊不是最優的值。(其實對于最好設置為真實物理內存大小的0.8)
錯誤6:Too many fetch-failures Answer: 出現這個問題主要是結點間的連通不夠全面。1)檢查、/etc/hosts 要求本機ip 對應 服務器名
要求要包含所有的服務器ip + 服務器名 2)檢查.ssh/authorized_keys 要求包含所有服務器(包括其自身)的public key 錯誤7:處理速度特別的慢 出現map很快 但是reduce很慢 而且反復出現 reduce=0% Answer: 結合第二點,然后修改可用內存大小。
conf/hadoop-env.sh 中的export HADOOP_HEAPSIZE=4000 錯誤8:能夠啟動datanode,但無法訪問,也無法結束的錯誤
在重新格式化一個新的分布式文件時,需要將你NameNode上所配置的dfs.name.dir這一namenode用來存放NameNode 持久存儲名字空間及事務日志的本地文件系統路徑刪除,同時將各DataNode上的dfs.data.dir的路徑 DataNode 存放塊數據的本地文件系統路徑的目錄也刪除。如本此配置就是在NameNode上刪除/home/hadoop/NameData,在DataNode上刪除/home/hadoop/DataNode1和/home/hadoop/DataNode2。這是因為Hadoop在格式化一個新的分布式文件系統時,每個存儲的名字空間都對應了建立時間的那個版本(可以查看/home/hadoop /NameData/current目錄下的VERSION文件,上面記錄了版本信息),在重新格式化新的分布式系統文件時,最好先刪除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 出現這種情況大多是結點斷了,沒有連接上?;蛘?/p>
mapred.tasktracker.map.tasks.maximum 的設置 超過 cpu cores數目,導致出現獲取不到文件。
錯誤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 網上說,將/hbase刪除;重啟hbase后,可以正常應用了。但是我找不到/hbase目錄,只好自己重新刪除掉一些hadoop文件,重新生成文件管理系統。
還有一個可能是,配置錯了/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集群的監控和配置調優工作;
3.負責Hadoop平臺的用戶管理、權限分配、資源分配;
4.負責集群服務器軟件的安裝、維護、部署、更新;
Hadoop運維工程師崗位職責(二)
1.負責高并發,大存儲和實時流的Hadoop/spark大數據平臺規劃,運維,監控和優化工作;
2.保證Hadoop/spark平臺各核心服務運行的穩定、高效;
___對Hadoop/spark平臺運維不斷優化,提升數據產品的質量和響應速度;
4.開發各種Hadoop大數據自動化運維與監控工具;
___平臺大數據環境的部署維護和技術支持;
6.應用故障的處理跟蹤及統計匯總分析;
7.應用安全,數據的日常備份和應急恢復。
Hadoop運維工程師崗位職責(三)
1、負責移動大數據中心的建設與維護;
2、負責安徽移動hadoop集群的故障排查、解決;
3、其他省份hadoop項目建設提供技術支持。
Hadoop運維工程師崗位職責(四)
1.負責Hadoop及相關組件的部署和維護,保證其穩定運行;
2.開發和使用Hadoop大數據自動化運維與監控工具;
3.基于大數據應用需求,不斷調整和優化Hadoop框架及組件的配置,提升性能;
4.為數據倉庫、數據挖掘建模等數據應用項目提供運行環境支持;
Hadoop運維工程師崗位職責(五)
1.hadoop集群運維、監控、開發;
2.hadoop生態圈框架部署、故障處理、異常排查等基本工作;
___對有助于提升集群處理能力、高可用性、擴展性的各種解決方案進行跟蹤和落地;
4.解決海量數據不斷增長面臨的挑戰,解決業務需求;
5、對Hadoop集群進行日常管理,保障系統正常運行;
第五篇:在三臺虛擬機上部署多節點Hadoop
cd /etc/network vi interfaces 進入vi后,編輯 auto eth0 iface eth0 inet static address IP地址 netmask 掩碼 gateway 網關
重啟SSH:
serivce ssh restart 重啟網卡: /etc/init.d/networking restart 取得root權限:
sudo passwd su 1.硬件環境
共有3臺機器,均使用的linux系統,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)這里有一點需要強調的就是,務必要確保每臺機器的主機名和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看來,節點分為Namenode和Datanode,其中Namenode只有一個,Datanode可以是很多;在MapReduce看來,節點又分為Jobtracker和Tasktracker,其中Jobtracker只有一個,Tasktracker可以是很多。我是將namenode和jobtracker部署在hadoop1上,hadoop2, hadoop3作為datanode和tasktracker。當然你也可以將namenode,datanode,jobtracker,tasktracker全部部署在一臺機器上。
2.目錄結構
由于Hadoop要求所有機器上hadoop的部署目錄結構要相同,并且都有一個相同的用戶名的帳戶。
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部署目錄結構如下:/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/目錄中,所有執行程序都在/home/hadoop/hadoop/bin目錄中。但是由于上述目錄中hadoop的配置文件和hadoop的安裝目錄是放在一起的,這樣一旦日后升級hadoop版本的時候所有的配置文件都會被覆蓋,因此建議將配置文件與安裝目錄分離,一種比較好的方法就是建立一個存放配置文件的目錄,/home/hadoop/hadoop/hadoop-config,然后將/home/hadoop/hadoop/conf/目錄中的masters,slaves,hadoop-env.sh三個文件拷貝到hadoop-config目錄中,并指定環境變量$HADOOP_CONF_DIR指向該目錄。環境變量在/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)來啟動和停止各個節點上的各種守護進程的,這就需要在節點之間執行指令的時候是不需要輸入密碼的方式,故我們需要配置SSH使用無密碼公鑰認證的方式。
首先要保證每臺機器上都裝了SSH服務器,且都正常啟動。實際中我們用的都是OpenSSH,這是SSH協議的一個免費開源實現。
apt-get install ssh 以本文中的3臺機器為例,現在hadoop1是主節點,它需要主動發起SSH連接到hadoop2,對于SSH服務來說,hadoop1就是SSH客戶端,而hadoop2, hadoop3則是SSH服務端,因此在hadoop2,hadoop3上需要確定sshd服務已經啟動。簡單的說,在hadoop1上需要生成一個密鑰對,即一個私鑰,一個公鑰。將公鑰拷貝到hadoop2上,這樣,比如當hadoop1向hadoop2發起ssh連接的時候,hadoop2上就會生成一個隨機數并用hadoop1的公鑰對這個隨機數進行加密,并發送給hadoop1,hadoop1收到這個加密的數以后用私鑰進行解密,并將解密后的數發送回hadoop2,hadoop2確認解密的數無誤后就允許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的內容復制/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只對其所有者有讀寫權限,其他人不允許有寫的權限,否則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配置已經完成,可以測試一下了,比如hadoop1向hadoop2發起ssh連接。
[hadoop@hadoop1:~]$ssh hadoop2 如果ssh配置好了,就會出現以下提示信息 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”文件中。第二次訪問這臺主機的時候就不會再顯示這條提示信息了。
然后你會發現不需要輸入密碼就可以建立ssh連接了,恭喜你,配置成功了,不過,別忘了測試本機ssh hadoop1。
(應該是只設置hadoop1對hadoop2發送ssh連接和hadoop1對hadoop3發送ssh連接,下面的需要配置嗎?)同樣,hadoop1對hadoop3發起ssh連接,再在hadoop3發起對hadoop1的連接。這里不在贅述。
4.Hadoop環境變量
在/home/hadoop/hadoop/hadoop-config目錄下的hadoop-env.sh中設置Hadoop需要的環境變量,其中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,內容如下: 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,我們根據需要修改如下:(注意:下面的配置文件中不要有中文或中文的符號,否則報錯)修改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已經在各個機器上部署完畢了,下面就讓我們開始啟動Hadoop吧。
7.啟動Hadoop 啟動之前,我們先要格式化namenode,先進入~/hadoop/目錄,執行下面的命令:
[hadoop@hadoop1 hadoop]$bin/hadoop namenode –format 不出意外,應該會提示格式化成功。如果不成功,就去hadoop/logs/目錄下去查看日志文件。
下面就該正式啟動hadoop啦,在bin/下面有很多啟動腳本,可以根據自己的需要來啟動。
* 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,查看現有文件:
[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 配置環境變量:
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權限(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并更改用戶所有權
wget http://mirror.bjtu.edu.cn/apache/hadoop/core/stable/hadoop-0.20.203.0rc1.tar.gz 我們采用的Hadoop版本是最新的Hadoop-0.20.2,可到Apache基金會官方主頁下載http://www.tmdps.cn/dyn/closer.cgi/hadoop/core,然后使用tar或直接解壓到/home/hadoop下,解壓后得到一個hadoop-0.20.2的一個文件夾。
安裝目錄:/usr/local/hadoop
更改所有權: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狀態監視地址 --SecondaryNameNode HTTP狀態監視地址 --每個job的map任務數 --每一個tasktracker同時運行的map任務數為2 --每一個tasktracker同時運行的reduce任務數為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.查看結果
$ 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)把公鑰內容添加到登錄認證文件中:cat 89_id_rsa.pub >> authorized_keys
(4)登錄到192.168.71.89 主機,使用ssh hadoop@192.168.77.213 進行連接213 主機,這時候會出現輸入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文件