1. 程式人生 > >搭建Hadoop+Hive+Mysql遇到的坑及解決辦法

搭建Hadoop+Hive+Mysql遇到的坑及解決辦法

1. 安裝環境

    硬體:三臺PC,配置 Intel i5 4 Core CPU, 16G memory,  2T 硬碟

    軟體: 兩臺PC為ubuntu 14.04, 一臺為ubuntu 16.04 ;    hadoop-2.8.0, hive-1.2.2, mysql 5.5.55, jdk-8u131-linux-x64.tgz (1.8.0_131)

    機器分配: 一臺ubutn 14.04的主機作maste, 其他作slave

    登陸帳號:方便期間,三臺機器上都建立使用者名稱/密碼為 hadoop/hadoop 的帳號

2.  各種問題及解決辦法

2.1.  從master通過ssh登陸slave後,.bashrc中增加的環境變數沒起作用, 直接在slave上 echo .bashrc中export的變數是正常的

問題原因: 建立hadoop帳號時,預設的shell 是/bin/sh 而不是/bin/bash ,導致ssh 登陸後根本不會執行.bashrc中的設定。

echo $SHELL 可檢視當前的shell  或 vim /etc/passwd 檢視使用者hadoop的最後一個欄位。

不同登陸方式執行的配置指令碼不同,主要涉及login shell 和non-login shell 的區別,簡單說區別如下,

 “login shell” 代表使用者登入, 比如使用 “su -“ 命令,或者用 ssh 連線到某一個伺服器上, 都會使用該使用者預設 shell 啟動 login shell 模式.
該模式下的 shell 會去自動執行 /etc/profile 和 ~/.profile 檔案, 但不會執行任何的 bashrc 檔案, 所以一般在 /etc/profile 或者 ~/.profile 裡我們會手動去 source bashrc 檔案, 或把.bashrc中的內容放在.profile中;
而 no-login shell 的情況是我們在終端下直接輸入 bash 或者 bash -c “CMD” 來啟動的 shell.該模式下是不會自動去執行任何的profile檔案.

解決辦法:原因知道了,解決就容易了。

a.  修改 hadoop 使用者的shell為/bin/bash;    ///  建立時設定 如,useradd -m -g hadoop hadoop -s /bin/bash ,或 sudo vim /etc/passwd 中修改,或  chsh

b.  .bashrc中的宣告語句放在.profile中或在.profile增加.bashrc的呼叫, 後者更方便,同時滿足兩種登陸方式。

    # include .bashrc if it exists  
    if [ -f "$HOME/.bashrc" ]; then  
        . "$HOME/.bashrc"  
    fi  

補充: 兩種登陸方式的更多區別,見   https://wido.me/sunteya/understand-bashrc-and-profile/

2.2  帳號hadoop 沒有執行sudo 的許可權

解決辦法:  修改//etc/sudoers 的400許可權為640後或 sudo chmod u+w /etc/sudoers後,sudo vim /etc/sudoers 增加    hadoop  ALL=(ALL:ALL)  ALL

或使用系統提供的工具修改,避免發生意外: sudo visudo /etc/sudoers 後增加上面hadoop 一行

注意: 安全期間,這個檔案的許可權是400即任何人是隻讀的,修改前不能隨便該為775等大許可權的,否則連sudo 都不能執行,一定要謹慎。

2.3  sudo 失效

修改/etc/sudoers檔案許可權過大後like 775 ,再執行sudo命令會報如下錯誤,sudo 失效。

     sudo echo $PATH
     sudo: /etc/sudoers is world writable  
     sudo: no valid sudoers sources found, quitting  
     sudo: unable to initialize policy plugin 

解決辦法:

a. 如果記得root 密碼,切換成root使用者後把許可權改成640

b.  如果不記得root密碼或沒設定過root密碼,比較杯具,可以參照下文找回root密碼後再修改  http://jingyan.baidu.com/article/c843ea0b9e851077931e4aea.html

2.4  Hadoop 啟動相關

2.4.1   hadoop 啟動時提示JAVA_HOME沒設定

解決辦法:JAVA_HOME確實在.bashrc/.profile中設定了,echo $JAVA_HOME時也是對的。可能hadoop本身也需要設,最後在 hadoop/etc/hadoop/hadoop-env.sh 中

增加  export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_131

2.4.2  master上NameNode啟動失敗

ERROR org.apache.hadoop.hdfs.server.namenode.NameNode: Failed to start namenode.
org.apache.hadoop.hdfs.server.common.InconsistentFSStateException: Directory /home/hadoop/bigdata/data/hadoop/tmp/dfs/name is in an inconsistent state:storage directory does not exist or is not accessible.
        at org.apache.hadoop.hdfs.server.namenode.FSImage.recoverStorageDirs(FSImage.java:322)
        at org.apache.hadoop.hdfs.server.namenode.FSImage.recoverTransitionRead(FSImage.java:210)
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.loadFSImage(FSNamesystem.java:1012)
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.loadFromDisk(FSNamesystem.java:691)
        at org.apache.hadoop.hdfs.server.namenode.NameNode.loadNamesystem(NameNode.java:634)
        at org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(NameNode.java:695)
        at org.apache.hadoop.hdfs.server.namenode.NameNode.<init>(NameNode.java:898)
        at org.apache.hadoop.hdfs.server.namenode.NameNode.<init>(NameNode.java:877)
        at org.apache.hadoop.hdfs.server.namenode.NameNode.createNameNode(NameNode.java:1603)
        at org.apache.hadoop.hdfs.server.namenode.NameNode.main(NameNode.java:1671)
2017-06-12 15:06:31,419 INFO org.apache.hadoop.util.ExitUtil: Exiting with status 1
2017-06-12 15:06:31,420 INFO org.apache.hadoop.hdfs.server.namenode.NameNode: SHUTDOWN_MSG:

問題原因/home/hadoop/bigdata/data/hadoop/tmp/dfs/name 是我們在hadoop core-site.xml中設定的每個節點上的臨時資料夾目錄名字,許可權不足或多次啟動失敗後通過kill -9 kill 掉java程式後此目錄下的.lock檔案還在,導致下次再啟動時訪問不到而失敗。
解決辦法首先,確保此hadoop帳號對此目錄有讀寫許可權;再就是,每次啟動時確保沒有.lock檔案或刪除此目錄 rm -fr/home/hadoop/bigdata/data/hadoop/tmp/dfs/name.

解決後在master上執行jps 可看到NameNode程序is running. 

2.4.3  master上啟動SecondaryNameNode 失敗

java.net.ConnectException: Call From master/ to master:9000 failed on connection exception: java.net.ConnectException:Connection refused; For more details see:  http://wiki.apache.org/hadoop/ConnectionRefused
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at org.apache.hadoop.net.NetUtils.wrapWithMessage(NetUtils.java:801)
        at org.apache.hadoop.net.NetUtils.wrapException(NetUtils.java:732)

同時,master上執行 ssh -v localhost也報如下錯誤:

debug1: ssh_exchange_identification: WARN: Connectiong not allowed.
ssh_exchange_identification: read: Connection reset by peer

看來是本機的問題。通過  ps -ef | grep ssh 檢視只有ssh client在執行,sshd (ssh server)還沒執行。

問題原因ubuntu 中預設是不安裝ssh-server的,也就不會執行。

解決辦法:sudo apt-get install openssh-server ;  ps -ef | grep ssh 確保sshd 已執行,即下行:

root      1179     1  0 09:29 ?        00:00:00 /usr/sbin/sshd -D

2.4.5  slave 上啟動YARN時 NodeManager啟動失敗

FATAL org.apache.hadoop.yarn.server.nodemanager.containermanager.AuxServices: Failed to initialize mapreduce-shuffle
java.lang.IllegalArgumentException: The ServiceName: mapreduce-shuffle set in yarn.nodemanager.aux-services is invalid.The valid service name should only contain a-zA-Z0-9_ and can not start with numbers
        at com.google.common.base.Preconditions.checkArgument(Preconditions.java:88)
        at org.apache.hadoop.yarn.server.nodemanager.containermanager.AuxServices.serviceInit(AuxServices.java:114)
        at org.apache.hadoop.service.AbstractService.init(AbstractService.java:163)
        at org.apache.hadoop.service.CompositeService.serviceInit(CompositeService.java:107)
        at org.apache.hadoop.yarn.server.nodemanager.containermanager.ContainerManagerImpl.serviceInit(ContainerManagerImpl.java:262)
        at org.apache.hadoop.service.AbstractService.init(AbstractService.java:163)
        at org.apache.hadoop.service.CompositeService.serviceInit(CompositeService.java:107)
        at org.apache.hadoop.yarn.server.nodemanager.NodeManager.serviceInit(NodeManager.java:357)
        at org.apache.hadoop.service.AbstractService.init(AbstractService.java:163)
        at org.apache.hadoop.yarn.server.nodemanager.NodeManager.initAndStartNodeManager(NodeManager.java:636)
        at org.apache.hadoop.yarn.server.nodemanager.NodeManager.main(NodeManager.java:684)

很明顯,這是因為配置yarn-site.xml 時,沒注意對應value的格式要求,把yarn.nodemanager.aux-services的值使用了非法字元“-”, 正常值“a-zA-Z0-9_ and can not start with numbers“。

解決辦法:修改mapreduce-shuffle中間的"-"為下劃線“_", i.e. mapreduce_shuffle.  每個地方都要小心,再小心!!!

至此,Hadoop 已經能再master/slave機器上跑起來了。 分別執行jps 可以檢視狀態和程序。

$  hdfs fdsadmin -report  // 可檢視HDFS狀態

2.5  HIVE/Mysql啟動相關

2.5.1  缺少mysql JDBC Driver

解決辦法:到mysql 官網下載 mysql-connector-xxx.jar 或 sudo apt-get install libmysql-java ;

安裝後jar包將被放在  /usr/share/java/下,like  mysql-connector-java-5.1.28.jar and its soft link.

把這個jar包拷貝到 $HIVE_HOME/lib下即可。

注意: hive-site.xml 中配置JDBC Driver時的值要寫正確。

<name>javax.jdo.option.ConnectionDeriverName</name>

<value>com.mysql.jdbc.Deriver</value>    // 這裡是以com開頭,不要因為是開源專案而寫成org

2.5.2  再metastore所在的master上啟動metastore失敗

metadata.Hive (Hive.java:<clinit>(168)) - Failed to access metastore. This class should not accessed in runtime.
org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient
Caused by: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient
        at org.apache.hadoop.hive.metastore.MetaStoreUtils.newInstance(MetaStoreUtils.java:1523)
Caused by: MetaException(message:Could not connect to meta store using any of the URIs provided. Most recent failure: org.apache.thrift.transport.TTransportException: java.net.ConnectException:拒絕連線 (Connection refused)
        at org.apache.thrift.transport.TSocket.open(TSocket.java:187)
        at org.apache.hadoop.hive.metastore.HiveMetaStoreClient.open(HiveMetaStoreClient.java:421)
        at org.apache.hadoop.hive.metastore.HiveMetaStoreClient.<init>(HiveMetaStoreClient.java:236)

問題原因:hive-site.xml中配置了metastore儲存在遠端mysql 中,通過thrift://master:9083提供服務。懷疑可能與mysql 訪問許可權有關。

                   本地通過 mysql -hlocalhost -uxx -pxx 可以正常訪問,但通過mysql  -hmaster -uxx -pxx 訪問失敗   // xx 為mysql 中設定的username and password.

                   顯然,與mysql的配置有關. 預設情況下,mysql 僅偵聽localhost.

解決辦法: 注掉/etc/mysql/my.cnf中 bind_address=127.0.0.1

2.5.3  slave 上啟動hiveserver2失敗

[main]: server.HiveServer2 (HiveServer2.java:startHiveServer2(376)) - Error starting HiveServer2 on attempt 1, will retry in 60 seconds
java.lang.RuntimeException: Error applying authorization policy on hive configuration: java.lang.IllegalArgumentException: java.NET.URISyntaxException:Relative path in absolute URI: ${system:java.io.tmpdir%7D/$%7Bhive.session.id%7D_resources
        at org.apache.hive.service.cli.CLIService.init(CLIService.java:114)
        at org.apache.hive.service.CompositeService.init(CompositeService.java:59)
        at org.apache.hive.service.server.HiveServer2.init(HiveServer2.java:100)
        at org.apache.hive.service.server.HiveServer2.startHiveServer2(HiveServer2.java:345)

問題原因:配置hive-site.xml 時,其中的system:java.io.tmpdir沒有設定有效值。
解決辦法: 建立hive的臨時目錄,如 $HIVE_HOME/iotmp , 找到hive-site.xml 中的system.:java.io.tmpdir, 並替換為所建立的hive 臨時目錄,主要有從下兩個配置項:

  <property>
    <name>hive.exec.local.scratchdir</name>
    <value>/home/hadoop/bigdata/hive/iotmp</value>
    <description>Local scratch space for Hive jobs</description>
  </property>
  <property>
    <name>hive.downloaded.resources.dir</name>
    <value>/home/hadoop/bigdata/hive/iotmp/${hive.session.id}_resources</value>
    <description>Temporary local directory for added resources in the remote file system.</description>
  </property>

2.5.4 hive命令列執行SQL語句時報錯 “Illegal character in scheme name at index 0: file://home/hadoop/bigdata/hbas...."

    居然是hive/hive-site.xml中配置的這段文字中沒太注意格式,每個file:///之間不能有空格,有空格就會報這個錯;同時這裡file:後面是三個///。

   重要的事情說三遍不能有空格,三個///,不能有空格,三個///,不能有空格,三個///

  <property>
    <name>hive.aux.jars.path</name>
    <value>file:///home/hadoop/bigdata/hbase/lib/hbase-common-1.2.6.jar,file:///home/hadoop/bigdata/hbase/lib/protobuf-java-2.5.0.jar,file:///home/hadoop/bigdata/hive/lib/hive-hbase-handler-1.2.2.jar,file:///home/hadoop/bigdata/hive/lib/zookeeper-3.4.6.jar</value>
    <description>The location of the plugin jars that contain implementations of user defined functions and serdes.</description>

至此,整體環境已經配置完成,命令列中啟動hive已經可以看到 hive> , 即將進入HIVE的神奇世界, YEAH!!!

3. HIVE 基本操作

準備:touch hive.txt , input some formated value like hive test \n  111\t hello \n 222 \t world\n ...

實際上,在$HIVE_HOME/examples/files已有很多實驗用的資料來源檔案,queries目錄下有現成的各種SQL query語句示例。

hive > create database hive1 (id int, name string) row format delimited fields terminated by '\t';

hive > show tables;

hive > show databases;

hive > load data local inpath '/home/hadoop/hive/hive.txt' overwrite into table hive1;   /// load hive.txt into db hive1

hive > select * from hive1;

hive >

致謝:

環境得以搭建完成,受益於遇到問題時從網上查的相關資源,這裡不一一羅列,個別問題在幾篇的基礎上整理後解決。

完成此文,為便於自己後續回顧參考,也方便大家遇到問題時儘量通過一篇可以搞定!

後續進階中如遇新問題,屆時再補充!

後續參考:

1. 搭建hive的問題集錦: http://www.cnblogs.com/qifengle-2446/p/6424426.html