windows平臺搭建本地hive訪問的測試環境

簡介環境搭建與效果演示更細節的搭建方法搭建HDFS、Spark或hive的前提已經有了遠程可訪問的測試集羣搭建hadoop2.7.2修改hadoop配置格式化hdfs測試搭建spark-2.4.5解壓hive-2.1.0創建hive元數據庫的schema測試spark-sqlspark-sql訪問已經被hive創建的表出現的問題測試hivejupyter中使用pyspark使用pyspark訪問本地hive測試pyspark

簡介

學習大數據最痛苦和費時間的就是入門時的環境搭建,對於大數據工程師而言,這個過程必不可少,但對於一些簡單的測試,每次都要打開自己搭建好的虛擬機,未免有些麻煩。

對於數據分析師而言,一般只需要使用hive和spark就好,搭建集羣實在是一件費力沒有效果的事。如果有一種方法讓數據分析師能夠在不搭建linux集羣的情況下就能把spark,hive在本地跑起來直接使用,那或許會非常方便。

我爲了讓需要使用大數據組件的朋友很方便的在本地使用hive和spark,已經多次測試了從零到1在windows平臺下搭建hadoop、hive和spark,並且直接跑起來。爲了減少廣大讀者環境帶來的坑,我刪除了原有的老版本,專門下載新版本的spark和對應的hadoop版本進行測試。

按照本文的方法搭建好之後,你就可以直接在windows上啓動hdfs、hive和spark各組件,並直接跑起來,然後我會演示如何使用python調用spark,並讓pyspark訪問現有的hive集羣的數據。

每個人機器的環境也都不一樣,我之所以寫這篇文章這麼久就是反覆考慮大多數人可能出現的環境問題,但仍然不可能面面俱到。我已經在自己機器上測試通過,若有讀者測試中遇到問題無法解決,歡迎反饋。

前面windows下pyspark訪問hive所需的環境部分,是演示windows基礎環境的搭建,如果你已經有了現成的可以直接遠程連接的測試集羣,則不需要在本地搭建額外的測試集羣可以直接跳過不讀本文,但本文提到的一個圖形化操作HDFS的工具或許對你有用,它支持windows遠程連接HDFS集羣,也支持連接使用了kerberos認證的HDFS的集羣。

爲了大家的方便,我已經將本文涉及的配置好的包和工具上傳到網盤,下載地址:

鏈接:https://pan.baidu.com/s/1XIHFg6sO02HKwtGhBQl5qQ
提取碼:5cmd

部分新手可能閱讀本文後依然花了很長時間才把本地環境搭建好,初次搭建對於你來說可能很複雜很費時,但想想每次測試都不用再都打開虛擬機了,其實相對來說就省了很多時間,除非你以後不打算再玩大數據。另外,在本地linux虛擬機上跑程序比直接在宿主機上跑程序慢很多,相對每次基礎測試都帶來的時間節省,我覺得還是很值得的。

最後將演示如何使用python調用spark,並用pyspark訪問現有的hive集羣。你也可以把你現有集羣的hive配置按照文章最後一部分的方法放入指定目錄中,使pyspark直接訪問你已經配置的hive集羣。

環境搭建與效果演示

已經給大家錄製了相應的操作視頻,整個搭建過程不算上講解僅需5分鐘,快來看看吧:

好本視頻已經演示瞭如何在windows搭建訪問hive所需的環境,下次公衆號data_xxm還將分享圖形化連接Hive的工具–SQuirrel Sql Client的使用,歡迎持續關注噢。

更細節的搭建方法

下面的方法是全部自己下載包的情況下如何搭建,所以過程有些繁瑣,上面的方法已經能夠讓你成功快速的搭建整個過程,不想了解細節的下面的內容都幾乎可以不用再看啦。

搭建HDFS、Spark或hive的前提

電腦中已經安裝過java1.8版本,並將JAVA_HOME配置到環境變量中,PATH環境變量也添加了

%JAVA_HOME%\bin%JAVA_HOME%\jre\bin

爲了遠程管理並共享hive元數據庫,我們使用mysql關係型數據庫作管理。使用其他關係型數據庫也可以,但本文只演示使用mysql作爲hive元數據庫。

已經有了遠程可訪問的測試集羣

那本章你就基本不用看了,除非你也想在windows本地搭建一個。

僅需要python調用pyspark,那你只需要電腦本身已經安裝了python3.6以上版本即可,沒有jupyter就運行以下命令安裝

pip install jupyter

然後按照文章 最後一部分的方法 將hive配置文件添加到pip所安裝的庫對應的目錄中。

搭建hadoop2.7.2

下載hadoop2.7.2版本的包:http://archive.apache.org/dist/hadoop/core/hadoop-2.7.2/hadoop-2.7.2.tar.gz,將其解壓到你喜歡的位置。

例如我解壓到D:/jdk中,然後將D:\jdk\hadoop-2.7.2重命名爲D:\jdk\hadoop

配置環境變量HADOOP_HOME=D:\jdk\hadoop

image-20200503091751881

Path環境變量本質上是一個;分割的路徑字符串,再向Path中添加

%HADOOP_HOME%\bin%HADOOP_HOME%\sbin這兩個路徑

例如Path原本的值爲

==C:\Windows\system32;C:\Windows==

添加後就是

==C:\Windows\system32;C:\Windows;%HADOOP_HOME%\bin;%HADOOP_HOME%\sbin==

下載已經編譯好的window平臺的hadoop,版本爲2.7.2

http://w3.153.d3s1puv.cn:82/uploadfile/2018/binwin7hadoop.rar

將其解壓到%HADOOP_HOME%路徑裏面,覆蓋bin目錄中的文件

然後將%HADOOP_HOME%\bin\hadoop.dll複製到C:\Windows\System32

image-20200503092322659

修改hadoop配置

core-site.xml配置:

<?xml version="1.0" encoding="UTF-8"?>

<configuration>
    <!--設置hdfs可以被訪問的ip,以及訪問端口-->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:9000</value>
    </property>
    <!--hdfs數據文件的存放位置-->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/tmp/hadoop/data</value>    
    </property>
    <!--被刪除的文件在垃圾箱的保留分鐘數,爲0表示禁用垃圾桶,被刪除的文件會直接被刪除-->
    <!--
    <property>
        <name>fs.trash.interval</name>
        <value>1440</value>
    </property>
    -->
    <!--
hadoop.proxyuser.$superuser.hosts    配置該superUser允許通過代理訪問的主機節點
hadoop.proxyuser.$superuser.groups    配置該superUser允許代理的用戶所屬組
hadoop.proxyuser.$superuser.users    配置該superUser允許代理的用戶
下面配置了Administrator可以代理訪問的主機節點和用戶所屬組爲全部
    -->
    <property>
            <name>hadoop.proxyuser.Administrator.hosts</name>
            <value>*</value>
    </property>
    <property>
            <name>hadoop.proxyuser.Administrator.groups</name>
            <value>*</value>
    </property>
</configuration>

hdfs-site.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>
      <!--副本數量,只用於做本地測試,所以只用1個副本節省空間-->
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
    <!---不進行權限檢查-->
    <property>
        <name>dfs.permissions</name>
        <value>false</value>
    </property>
</configuration>

格式化hdfs

命令行中輸入命令hdfs namenode -format

D:\>hdfs namenode -format

注意:我在hadoop.tmp.dir的配置中爲/tmp/hadoop/data沒有加盤符,此時命令行執行位置所在路徑決定了hdfs的數據文件的存放位置。由於我在D盤執行的命令,所以最終hdfs的數據文件會放在D:\tmp\hadoop\data中。當然也可以配置爲/D:/tmp/hadoop/data(最前面的/不能省略,也不允許在/前面加file:,必須以/開頭+盤符才能指定盤符),這樣即使在C盤執行命令也會放在D盤。

image-20200503095650652

出現has been successfully formatted.表示格式化成功。

測試

啓動hdfs:

start-dfs.cmd
image-20200503095939066

會啓動namenodedatanode兩個進程。

遊覽器訪問http://localhost:50070/可查詢UI界面:

image-20200503100111085

用HDFS遊覽器訪問剛纔搭建好的HDFS:

image-20200504071127214

地址和端口填寫上面連接HDFS的webUI的ip和端口,上面的連接地址是http://localhost:50070/,所以地址填localhost,端口填50070。

然後測試上傳文件:

image-20200503100522578

也沒有問題,想要這個小工具可以關注公衆號data_xxm後臺留言獲取噢。

再測試一下shell命令行裏訪問:

image-20200503100819154

也完全正常。

搭建spark-2.4.5

下載spark-2.4.5:http://archive.apache.org/dist/spark/spark-2.4.5/spark-2.4.5-bin-hadoop2.7.tgz

解壓到你喜歡的任意位置,例如我解壓到D:\jdk,就將D:\jdk\spark-2.4.5-bin-hadoop2.7\bin添加到Path環境變量中,然後在D:\jdk\spark-2.4.5-bin-hadoop2.7\jars中放入mysql的驅動jar包,例如mysql-connector-java-5.1.38-bin.jar

解壓hive-2.1.0

下載:http://archive.apache.org/dist/hive/hive-2.1.0/apache-hive-2.1.0-bin.tar.gz

解壓到你喜歡的任意位置,例如,我解壓到D:\jdk

配置環境變量HIVE_HOME=D:\jdk\apache-hive-2.1.0-bin

並向Path環境變量中加入%HIVE_HOME%\bin

conf中新建hive-site.xml文件,內容如下:

<configuration>
    <property>
        <name>javax.jdo.option.ConnectionURL</name>
        <value>jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true</value>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionUserName</name>
        <value>root</value>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionPassword</name>
        <value>123456</value>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionDriverName</name>
        <value>com.mysql.jdbc.Driver</value>
    </property>

    <property>
        <name>hive.metastore.warehouse.dir</name>  
        <!--hive的數據存儲目錄,指定的位置在hdfs上的目錄-->  
        <value>/tmp/hive/warehouse</value>
    </property>
    <property>
        <name>hive.cli.print.header</name>
        <value>true</value>
    </property>

    <property>
        <name>hive.cli.print.current.db</name>
        <value>true</value>
    </property>
</configuration>

前三項分別是你的mysql連接url,用戶名和密碼,按照實際情況修改即可。連接url中hive也可以修改爲其他名字,表示hive存儲元數據的數據庫的名稱。

hive.metastore.warehouse.dir表示默認情況hive管理表的數據存儲位置。

注意:上面hive-site.xml配置了hive.metastore.warehouse.dir=/tmp/hive/warehouse,這個路徑在spark中會識別爲以程序啓動所在盤符下的本地路徑,可以指定具體盤符,例如D:/tmp/hive/warehouse則路徑不受程序啓動位置的限制。

而在這個配置的hive下創建數據庫或表,/tmp/hive/warehouse會識別爲以fs.defaultFS爲前綴的hdfs路徑,在本文的配置中就是hdfs://localhost:9000/tmp/hive/warehouse,如果hive.metastore.warehouse.dir被配置爲D:/tmp/hive/warehouse則hive會認爲是hdfs://localhost:9000/D:/tmp/hadoop/data導致hive無法創建不指定手動指定路徑主控表。

要想讓hive創建的表也被識別爲本地路徑,必須配置爲file:/D:/tmp/hive/warehouse指定file協議。

創建hive元數據庫的schema

hive啓動在需要mysql中存在scheme 表格結構,在hive1.x版本原本是可以自動創建的,但2.x版本中必須手工通過下面這個命令:

schematool --dbType mysql --initSchema

但是這個命令在windows平臺不好使,會報如下錯誤,當前路徑都會自動給你切換:

D:\jdk\apache-hive-2.1.0-bin\bin\ext>schematool.cmd --dbType mysql --initSchema
C:\Windows\system32
找不到文件
系統找不到指定的路徑。

C:\Windows\System32>

其實我之前在windows平臺上搭建hive,使用schematool命令,但這次爲了演示卻不成功了。

如果有讀者知道在windows平臺如何正確使用schematool命令,歡迎討論。

既然這個方法不好使,所以我就直接從原理層面直接操作了。這個命令本質是使用了預先定義保存在模板文件的一些sql語句,根據不同的條件選擇模板問題,並填充裏面的變量。

但是我經過觀察發現,這些模板文件需要變量填充的部分執行與否都無所謂,根本不用自己再開發一個填充變量的程序,直接執行這些模板文件的合法sql腳本內容即可。

這樣就能實現創建scheme的效果,具體scheme模板文件的路徑是%HIVE_HOME%/scripts/metastore/upgrade/mysql/ 目錄下的 hive-schema-2.1.0.mysql.sql  (其他關係型數據庫同理)。

於是只要無視錯誤的導入D:\jdk\apache-hive-2.1.0-bin\scripts\metastore\upgrade\mysql\hive-schema-2.1.0.mysql.sql腳本到hive數據庫就可以創建元數據庫scheme了。

下面具體操作一下,先創建hive數據庫(字符集必須指定爲latin1,排序規則默認值即可):

image-20200503122606257

再導入sql腳本(下圖使用sqlyog操作):

image-20200503122904338

共導入46張表(使用Navicat查看):

image-20200503123603130

測試spark-sql

首先將%HIVE_HOME%\hive-site.xml文件添加到D:\jdk\spark-2.4.5-bin-hadoop2.7\conf目錄下:

image-20200503184733865

運行D:\jdk\spark-2.4.5-bin-hadoop2.7\bin\spark-sql2.cmd並創建幾張表(已經將D:\jdk\spark-2.4.5-bin-hadoop2.7\bin添加到Path環境變量中):

image-20200503141053526
image-20200503142433513

導入數據:

由於我配置的數據存儲路徑都是本地文件系統,未使用hdfs文件系統,則直接將數據文件扔到存儲表對應的目錄即可,本文中的配置就是D:\tmp\hive\warehouse下面的子目錄。

上述表涉及的數據可見:

http://mp.weixin.qq.com/mp/homepage?__biz=MzA4NzcxOTQ1NA==&hid=2&sn=24824d7bbf36edb89470e03efa2d1545&scene=18#wechat_redirect

測試查詢:

image-20200503133949360
image-20200503134009343

spark-sql訪問已經被hive創建的表出現的問題

如果你是按照上面的方法,通過spark創建的hive表,是不會遇到這個坑的,但是如果上面的表你是通過hive先創建的,再次打開spark-sql就有可能會報如下錯誤:

Caused by: java.lang.RuntimeException: The root scratch dir: /tmp/hive on HDFS s
hould be writable. Current permissions are: rwx------
        at org.apache.hadoop.hive.ql.session.SessionState.createRootHDFSDir(Sess
ionState.java:612)
        at org.apache.hadoop.hive.ql.session.SessionState.createSessionDirs(Sess
ionState.java:554)
        at org.apache.hadoop.hive.ql.session.SessionState.start(SessionState.jav
a:508)
        ... 14 more

就是因爲當前用戶不具備對\tmp\hive的操作權限:

D:\>winutils ls \tmp\hive
drwx------ 1 BUILTIN\Administrators XIAOXIAOMING\None 0 May  4 2020 \tmp\hive

解決辦法是把\tmp\hive目錄的權限改爲777:

D:\>winutils chmod 777 \tmp\hive

D:\>winutils ls \tmp\hive
drwxrwxrwx 1 BUILTIN\Administrators XIAOXIAOMING\None 0 May  4 2020 \tmp\hive

然後再次嘗試即可順利訪問。

winutils更多的操作方法可直接敲winutils命令查看:

D:\>winutils
Usage: winutils [command] ...
Provide basic command line utilities for Hadoop on Windows.

The available commands and their usages are:

chmod          Change file mode bits.

chown          Change file owner.

groups         List user groups.

hardlink       Hard link operations.

ls             List file information.

readlink  Print the target of a symbolic link.

systeminfo     System information.

task           Task operations.
Usage: task create [OPTOINS] [TASKNAME] [COMMAND_LINE]
       task createAsUser [TASKNAME] [USERNAME] [PIDFILE] [COMMAND_LINE]
         Creates a new task jobobject with taskname as the user provided
       task isAlive [TASKNAME]
         Checks if task job object is alive
       task kill [TASKNAME]
         Kills task job object
       task processList [TASKNAME]

service        Service operations.

測試hive

spark-sql可以在不啓動hdfs的情況下使用,但hive即使所有表都指定本地文件系統,使用前也必須先啓動hdfs,否則出現如下錯誤:

image-20200503142934453

正確啓動後:

image-20200503143100784

查看一下hive表:

image-20200503134529643
image-20200503143146018

windows版的hive最大的缺點就是日誌過多,另外是一些分區修護的命令不好使,但是常規的查詢還是可以在hive上測試的。

本人已經多次測試修改hive的多個log4f配置文件,仍然沒有生效,INFO日誌依然打印的不停,如果有哪位大佬知道改那個配置可以取消這些煩人的日誌,歡迎討論。

準備執行:

image-20200503143224405

運行結果:

image-20200503143311380

jupyter中使用pyspark

使用pyspark訪問本地hive

首先安裝與本地hadoop兼容的pyspark版本,跟前面的spark版本一致即可:

pip install pyspark==2.4.5

然後將hive-site.xml配置文件放入D:\Anaconda3\Lib\site-packages\pyspark\conf中

D:\Anaconda3\Lib\site-packages更換爲命令pip show pyspark查看到的地址(Location)

(base) C:\Users\Administrator>pip show pyspark
Name: pyspark
Version: 2.4.5
Summary: Apache Spark Python API
Home-page: https://github.com/apache/spark/tree/master/python
Author: Spark Developers
Author-email: [email protected]
License: http://www.apache.org/licenses/LICENSE-2.0
Location: d:\anaconda3\lib\site-packages
Requires: py4j
Required-by:

再將mysql連接驅動例如mysql-connector-java-5.1.38-bin.jar放入D:\Anaconda3\Lib\site-packages\pyspark\jars中。

爲了加速pip的下載,可以在~/pip中添加pip.ini文件,內容如下:

[global]
trusted-host=mirrors.aliyun.com
index-url=http://mirrors.aliyun.com/pypi/simple/

測試pyspark

先獲取SparkSession和SparkContext對象:

from pyspark.sql import SparkSession
from pyspark.sql import Row

spark = SparkSession \
    .builder \
    .appName("Python Spark SQL Hive integration example") \
    .enableHiveSupport() \
    .getOrCreate()
sc = spark.sparkContext
spark
image-20200503202152489

測試一下文本讀取,先獲取自己所在目錄下所有文件的行數:

textFile = spark.read.text(".")
textFile.count()
5031

獲取第一條數據:

textFile.first()
Row(value='Sun May 03 06:58:24 CST 2020 Thread[Thread-4,5,main] Cleanup action starting')

測試一下sql,先獲取存在的表:

spark.sql("show tables").show()
+--------+---------+-----------+
|database|tableName|isTemporary|
+--------+---------+-----------+
| default|   xxm_t1|      false|
| default|   xxm_t2|      false|
| default|   xxm_t3|      false|
| default|   xxm_t4|      false|
| default|   xxm_t5|      false|
+--------+---------+-----------+

順利訪問到前面創建的表。

測試窗口函數:

sql="""
SELECT cookieid,
createtime,
pv,
SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime) AS pv1, -- 默認爲從起點到當前行
SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS pv2, --從起點到當前行,結果同pv1
SUM(pv) OVER(PARTITION BY cookieid) AS pv3,                --分組內所有行
SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS pv4,   --當前行+往前3行
SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) AS pv5,    --當前行+往前3行+往後1行
SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS pv6   ---當前行+往後所有行  
FROM xxm_t1
"""
spark.sql(sql).show()
+--------+----------+---+---+---+---+---+---+---+
|cookieid|createtime| pv|pv1|pv2|pv3|pv4|pv5|pv6|
+--------+----------+---+---+---+---+---+---+---+
| cookie1|2015-04-10|  1|  1|  1| 26|  1|  6| 26|
| cookie1|2015-04-11|  5|  6|  6| 26|  6| 13| 25|
| cookie1|2015-04-12|  7| 13| 13| 26| 13| 16| 20|
| cookie1|2015-04-13|  3| 16| 16| 26| 16| 18| 13|
| cookie1|2015-04-14|  2| 18| 18| 26| 17| 21| 10|
| cookie1|2015-04-15|  4| 22| 22| 26| 16| 20|  8|
| cookie1|2015-04-16|  4| 26| 26| 26| 13| 13|  4|
+--------+----------+---+---+---+---+---+---+---+

順利執行。

關於sparksql的函數可參考:http://spark.apache.org/docs/latest/api/sql/index.html

當然sparksql對hive的函數幾乎全部都支持,只看hive的函數也可以。

測試一下機器學習:

from pyspark.mllib.linalg import Matrices, Vectors
from pyspark.mllib.regression import LabeledPoint
from pyspark.mllib.stat import Statistics

vec = Vectors.dense(0.1, 0.15, 0.2, 0.3, 0.25)  # a vector composed of the frequencies of events

# compute the goodness of fit. If a second vector to test against
# is not supplied as a parameter, the test runs against a uniform distribution.
goodnessOfFitTestResult = Statistics.chiSqTest(vec)

# summary of the test including the p-value, degrees of freedom,
# test statistic, the method used, and the null hypothesis.
print("%s\n" % goodnessOfFitTestResult)

mat = Matrices.dense(3, 2, [1.0, 3.0, 5.0, 2.0, 4.0, 6.0])  # a contingency matrix

# conduct Pearson's independence test on the input contingency matrix
independenceTestResult = Statistics.chiSqTest(mat)

# summary of the test including the p-value, degrees of freedom,
# test statistic, the method used, and the null hypothesis.
print("%s\n" % independenceTestResult)

obs = sc.parallelize(
    [LabeledPoint(1.0, [1.0, 0.0, 3.0]),
     LabeledPoint(1.0, [1.0, 2.0, 0.0]),
     LabeledPoint(1.0, [-1.0, 0.0, -0.5])]
)  # LabeledPoint(label, feature)

# The contingency table is constructed from an RDD of LabeledPoint and used to conduct
# the independence test. Returns an array containing the ChiSquaredTestResult for every feature
# against the label.
featureTestResults = Statistics.chiSqTest(obs)

for i, result in enumerate(featureTestResults):
    print("Column %d:\n%s" % (i + 1, result))
Chi squared test summary:
method: pearson
degrees of freedom = 4 
statistic = 0.12499999999999999 
pValue = 0.998126379239318 
No presumption against null hypothesis: observed follows the same distribution as expected..

Chi squared test summary:
method: pearson
degrees of freedom = 2 
statistic = 0.14141414141414144 
pValue = 0.931734784568187 
No presumption against null hypothesis: the occurrence of the outcomes is statistically independent..

Column 1:
Chi squared test summary:
method: pearson
degrees of freedom = 0 
statistic = 0.0 
pValue = 1.0 
No presumption against null hypothesis: the occurrence of the outcomes is statistically independent..
Column 2:
Chi squared test summary:
method: pearson
degrees of freedom = 0 
statistic = 0.0 
pValue = 1.0 
No presumption against null hypothesis: the occurrence of the outcomes is statistically independent..
Column 3:
Chi squared test summary:
method: pearson
degrees of freedom = 0 
statistic = 0.0 
pValue = 1.0 
No presumption against null hypothesis: the occurrence of the outcomes is statistically independent..

執行後UI界面的變化:

image-20200504110039485
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章