如何透過Greenplum查詢Hadoop HDFS上的資料

前言

這篇文章,是我在開發的資料視覺化系統的過程中,所猜測的資料庫結構,因為這個開發系統是這樣的:

  • 資料視覺化系統由我們開發,資料庫以及資料來源的建置由另外一間案主請的外包公司負責
  • 當初在開發的時候,我從專案經理得到的訊息為:之後他們資料庫所使用的是「PostgreSQL」,所以我在開發與測試環境中都使用此資料庫作為我們系統測試資料庫
  • 在移入內部網路時候,才發現資料庫的架構之不對勁

本文章中,是在探討我在將系統移入的過程中,如何一步步的發現資料庫的架構

資料庫架構

原本一開始聽到的架構是,我以為是長這樣的

  • 「1」的部份,我認為是我們系統透過PostgrSQL溝通,查詢我們要的資料
  • 「2」的部份,我認為是有固定排程工作(?),Hadoop上的放在HDFS上的資料會匯入到PostgreSQL資料庫中
  • 當初我聽到這樣資料庫的架構,我一直處在半信半疑的狀態,不過為了系統開發的時程,那時候也沒有想太多,就直接先按照這樣的架構去建立一個PostgrSQL來當作測試資料庫後開始開發系統了

後來,到後面的移入內網的時候,我慢慢從它們講的名詞猜出其實是長下面這樣子的架構。

一開始我還猜資料(HDFS)部份有使用HBase,不過後來廠商說只使用HDFS。

其架構流程如下:

  • 「1」的部份,就是我們系統會去向Greenplum資料庫請求我們要的資料
  • 「2」的部份,則是我們Greenplum資料庫會向放在Hadoop的HDFS上的資料載入到資料表並做查詢

資料庫架構差異

這兩者其實有很大的差異,其差別如下:

  • 我所想的是利用完全的PostgreSQL的所有特性,我們面對查詢的部份只有SQL查詢優化
  • 廠商所設計的架構,是目的為了要讓存放在HDFS上面的檔案可以透過SQL方式查詢,因此使用了基於PostgreSQL所改良的資料庫,叫做Greenplum
  • 透過此資料庫,可以建立外部資料表並指定HDFS上的檔案進行檔案的載入

Greenplum 資料庫建立外部資料表

本章節,就是在描述如何使用建立外部資料表來載入HDFS上的資料。

首先,先要了解,Greenplum 可以當作是一個查詢的介面,透過它去查詢資料。

並藉由此機制建立readable external table,可以讀取的協定如下:

  • host file system檔案系統上的檔案
  • an NFS server上的檔案 (NFS=Network file system)
  • Hadoop file system (HDFS).

外部資料表(external table)相關介紹

從官方文件中可以得知,這類的external table有分成下列幾種

  • CREATE EXTERNAL TABLE or CREATE EXTERNAL WEB TABLE
    • 這類是建立一個readable可以讀取的外部資料表,通常是載入外部的儲存資料空間做使用
    • 那也不能在此外部資料表上建立索引(indexes)
    • UPDATE, INSERT, DELETE, or TRUNCATE 等操作都不被允許
  • CREATE WRITABLE EXTERNAL TABLE or CREATE WRITABLE EXTERNAL WEB TABLE
    • 這類是建立一個可寫入資料的外部資料表,通常是要載入外部資料庫之後,變成單獨的資料表且會存放在Greenplum資料庫中
    • 此類型的外部資料表允許可以INSERT插入資料的動作
    • SELECT, UPDATE, DELETE or TRUNCATE 等操作都不被允許

在Greenplum官方範例文件中,有如下的敘述:

假設我們有一個資料庫檔案,叫做 sales,分區資料表方式如下圖:

其分區資料表概念就是,有一個資料表是parent table,那依照以月分區的方式建立多個child tables

分區的方式如下:

  • range partitioning: division of data based on a numerical range, such as date or price. (這個指的是利用某個欄位可以做日期範圍的分區,如此一來就可以)
  • list partitioning: division of data based on a list of values, such as sales territory or product line. (列表分區,以銷售資料來說,就是可以用銷售資料的類型或是產品線種類進行分區)

Example Exchanging a Partition with an External Table

本章節,會以Greenplum官方文件做範例,透過官方提供的sales範例來呈現如何做到建立外部資料表並將它們做成分區,以及如何讀取它們。

從上面解釋外部資料表的不同類型,我們可以知道可寫跟可讀的資料表上的差異,那為了要讓資料表可以寫入資料與查詢,我們要做的建立外部資料表方式步驟如下:

首先,我們需要先建立一個名叫sales的資料表,其SQL語法如下:


CREATE TABLE sales (id int, year int, qtr int, day int, region text)
DISTRIBUTED BY (id)
PARTITION BY RANGE (year)
( PARTITION yr START (2010) END (2014) EVERY (1) ) ;

  • 裡面包含了id, 年分, qtr 某個訊息的值, 日期以及地區
  • 這裡分區的方式是用年份來區分,那在我們外包的資料庫廠商則是用日期(年月日)作為分區的範圍
  • 分區會有一個範圍,則是起始與結束的年份,那用日期則是,開始日期到結束的日期,以上述的例子來說,就是建立2010到2013年份之間的sales資料

接著,要確定讀取外部資料的來源是存放在哪個地方,在此範例中,假設外部要存取的檔案是放在 gpfdist (Greenplum Parallel File Server)

接著先建立一個可以寫入的外部資料表,相關SQL語法如下:


CREATE WRITABLE EXTERNAL TABLE my_sales_ext ( LIKE sales_1_prt_yr_1 )
LOCATION ( 'gpfdist://gpdb_test/sales_2010' )
FORMAT 'csv'
DISTRIBUTED BY (id) ;

接著在建立一個readable可以讀取的外部資料表


CREATE EXTERNAL TABLE sales_2010_ext ( LIKE sales_1_prt_yr_1)
LOCATION ( 'gpfdist://gpdb_test/sales_2010' )
FORMAT 'csv' ;

接著從leaf child partition上的資料寫進先前步驟建立的external table中


INSERT INTO my_sales_ext SELECT * FROM sales_1_prt_yr_1 ;

接著把先前建立的external table與目前存在的leaf child partition table互相交換,相關SQL語法如下:


ALTER TABLE sales ALTER PARTITION yr_1
EXCHANGE PARTITION yr_1
WITH TABLE sales_2010_ext WITHOUT VALIDATION;

上面步驟做完之後,資料表就會變成:

  • 原來external table sales_1_prt_yr_1 就會變成 leaf child partition table
  • 原本的leaf child partition table sales_2010_ext就會變成 external table

接著把sales_2010_ext資料表,因為交喚之後,我們不需要external table了,所以可以把它移除。


DROP TABLE sales_2010_ext ;

接著我們把分區名稱,做一個修改,因為本來,分區名稱在建立sales資料表的時候是下列的分區名稱:

  • yr_1
  • yr_2
  • yr_3
  • yr_4

那也可以透過更改分區名稱,把 sales_1_prt_yr_1 資料表標註成這是一個external table,那這是一個可選的工作。相關語法如下:


ALTER TABLE sales RENAME PARTITION yr_1 TO yr_1_ext ;

讀取外部資料

從上述的章節,我們可以初步的知道如何建立外部資料表載入外部檔案並成為分區資料表的方式。那如果是要載入其他檔案系統上的檔案呢?

我們可以以廠商使用的HDFS為例:

在官方文件中,Greenplum 5.2.0版本時候,gphdfs已經廢棄了,這是一個Greenplum設計的協定,並專門去讀取在HDFS上的檔案用的。

官方強烈建議使用它們設計的另一個協定,叫做PXF (The Greenplum Platform Extension Framework),這是一個Greenplum所設計的統一介面協定。

所以建立外部資料表方式就可以改成:


CREATE EXTERNAL TABLE pxf_hdfs_text(location text, month text, num_orders int, total_sales float8)
LOCATION ('pxf://data/pxf_examples/pxf_hdfs_simple.txt?PROFILE=hdfs:text')
FORMAT 'TEXT' (delimiter=E',');

CSV 檔,也可以使用上述的SQL語法去建立相關的資料表

結論

  • 開發的系統與資料庫分開給不同的人做,讓我感覺就是在一開始的時候,就要知道對方確切的資料庫架構會長什麼樣子,以便日後開發系統上的順利。
    而不是等到系統已經完成,進入維護的時候,我才發現資料庫的架構是長這個樣子。要再去改動SQL查詢的時候的成本就會變得很高。
  • 一個專案經理懂不懂技術,就可以從一個案子知道。
    因為當初我所聽到的架構與我和廠商DBA做完溝通之後,完全想到跟猜測的根本是不一樣的東西。
  • 這種資料庫架構來說,不能說是不好,這是一個可以用SQL上讀取放在HDFS或是其他檔案系統上的檔案,這樣的方式也是讓其他人能夠較輕易的讀取Haddop HDFS 上的檔案。

參考資料

  • NFS
  • https://gpdb.docs.pivotal.io/5200/pxf/access_hdfs.html
  • https://gpdb.docs.pivotal.io/5200/pxf/hdfs_text.html#profile_text
  •  http://docs.greenplum.org/5160/admin_guide/ddl/ddl-partition.html#topic_yhz_gpn_qs
    • 「Exchanging a Leaf Child Partition with an External Table」之章節
  • https://gpdb.docs.pivotal.io/5200/admin_guide/external/g-working-with-file-based-ext-tables.html
  • https://gpdb.docs.pivotal.io/560/ref_guide/sql_commands/CREATE_EXTERNAL_TABLE.html

安裝Hue管理HBase資料庫

前言

由於工作的關係,需要將HBase安裝好之後,找一個能夠管理資料庫的介面,找了又找,最後找了這個,叫做Hue的資料庫管理介面。本文章中,會教導該如何在Ubuntu 16.04上面將此資料庫管理介面安裝起來並執行。

前置環境

在安裝Hue之前,需要有下列的環境與先需先安裝好幾個套件。

  • 一個乾淨的Ubuntu 16.04
  • 已經安裝好Hadoop與HBase,若尚未安裝,請先參考這篇文章
  • 因為需要編譯,需要安裝好編譯的工具與編譯期間需要用到的函式庫。
    # 更新套件的鏡像來源
    sudo apt-get update
    sudo apt-get install maven \
    git-core \
    make \
    libffi-dev \
    python-dev \
    krb5-config \
    libkrb5-dev \
    libssl-dev \
    libsasl2-dev \
    libsasl2-modules-gssapi-mit \
    libldap2-dev \
    libxml2 \
    libxml2-dev \
    libxslt1.1 \
    libxslt1-dev \
    libsqlite3-dev \
    libgmp3-dev \
    libmysqlclient-dev
    

    安裝編譯工具

    sudo apt-get install build-essential autoconf libtool pkg-config python-opengl python-imaging python-pyrex python-pyside.qtopengl idle-python2.7 qt4-dev-tools qt4-designer libqtgui4 libqtcore4 libqt4-xml libqt4-test libqt4-script libqt4-network libqt4-dbus python-qt4 python-qt4-gl libgle3 python-dev
    

下載Hue專案

在本次步驟,我們使用Git指令將Hue專案下載回來。


git clone https://github.com/cloudera/hue

編譯Hue Web App

下載Hue專案回來之後,接著切換到hue專案底下,並執行make apps


cd ~/hue

make apps

編譯完成之後,我們可以使用下面的指令試著將server跑起來。


build/env/bin/hue runserver

跑起來之後,用瀏覽器訪問,localhost:8000就可以看到如下的畫面了。

成功之後,記得按下ctrl+c停止Hue server並回到原來打指令的模式。

設定HBase

在正式將Hue server弄起來之前,需要先將HBase設定好。

首先,先使用root使用者執行 netstat指令查看9090是否有人使用。


sudo netstat -nl|grep 9090

確定沒有人使用之後,則切換到/usr/local/hbase/bin底下並執行下面的指令


hbase-daemon.sh start thrift

執行完成上述的指令之後,我們可以使用jps指令,並可以看到多了一個叫做ThriftServer的跑起來了。

設定Hue設定檔

接著我們要在Hue中設定有關於HBase的相關設定。照著下面指令,將設定檔案開啟。


vim ~/hue/desktop/conf/pseudo-distributed.ini

接著找到[hbase]的設定地方,按照下面的截圖,把一些設定前面的註解拿掉與修改設定值。

完成之後,Hue的HBase相關設定就完成了。

用Nginx反向代理讓外網也可連Hue

因為Hue跑此server的時候,只在內網跑,監聽的位址是localhost,也就是127.0.0.1

那我們如果是使用VPS,把Hue架設與運行起來好之後,我們在外網是看不到server的畫面。因此我們可以安裝Nginx並使用反向代理的方式,把畫面接出來。

首先先安裝Nginx


sudo apt-get update

sudo apt-get install nginx

設定反向代理的位址


# 打開Nginx設定檔

sudo vim /etc/nginx/sites-available/default

找到下面的location / 區塊,把區塊中內容改成下面的設定,接著存檔並離開。


location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
proxy_pass http://localhost:8000;
}

檢查Nginx設定檔是否有誤


sudo nginx -t

看到下面的截圖之後,就代表設定檔的語法沒有問題。

重新載入Nginx服務


sudo service nginx reload

做完上述的設定之後,我們在使用nohup指令將Hue server跑在背景執行。


nohup build/env/bin/hue runserver &

執行完nohup之後,記得要再按一次enter鍵,才會回到原來指令模式。

接著可以用ps指令查看Hue是不是正確在背景中執行,若正確的話,會與如下圖一樣,途中,黃色部份的PID會有所不同,是正常的。

若有需要設定Hue的話,則先需要將這兩個process停止,停止的方式則是用kill指令,並在kill 後面加入要kill 的 PID,若以下面的截圖作為例子,則是將8136與8146停止,其指令如下:


kill 8136 8146

參考資料

 

在Ubuntu 16.04上安裝HBase

前言

在前面的文章中,我們已經把Hadoop安裝起來了,那本篇文章,則是要接續前面的部份,將HBase也一併安裝起來。

前置條件

  • 需要完整的安裝並正常運行Hadoop,若還沒完成者,請先到此篇文章進行安裝。

第一步:下載HBase壓縮檔

這邊一樣,我們先使用wget指令下載HBase壓縮檔,下載完成之後,進行解壓縮並把整個檔案移到/usr/local/hbase,並將使用者權限修改為hadoop,相關指令如下。
這裡示範安裝HBase版本為1.4.7


wget http://apache.mirror.gtcomm.net/hbase/stable/hbase-1.4.7-bin.tar.gz
tar -zxvf hbase-1.4.7-bin.tar.gz
sudo mv hbase-1.4.7 /usr/local/hbase/
sudo chown -R hadoop /usr/local/hbase/

第二步:設定HBase環境變數

依照下面的方式,在~/.bashrc中設定相關的環境變數


export HBASE_HOME=/usr/local/hbase
export PATH=$PATH:$HBASE_HOME/bin

設定完成之後,別忘了使用source指令進行重新載入.bashrc檔

第三步:設定hbase-env.sh

在hbase-env.sh設定檔中,設定JAVA_HOME環境變數。相關指令如下:


cd /usr/local/hbase/conf

vim hbase-env.sh

並加入這一行:export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

編輯/usr/local/hbase/conf/hbase-site.xml設定檔案並將下列內容加到<configuration></configuration>之間,其內容如下:


<property>
<name>hbase.rootdir</name>
<value>hdfs://localhost:9000/hbase</value>
</property>

<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/hadoop/zookeeper</value>
</property>

<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>

第四步:執行HBase

使用下面的指令將HBase跑起來。


/usr/local/hbase/bin/start-hbase.sh

一樣,在執行過程中會需要打密碼,那就打hadoop使用者的密碼。

執行成功後如截圖所示:

接著執行HBase shell。


hbase shell

執行成功後如下截圖所示:

我們可以在HBase shell底下執行status命令來查看有沒有出現錯誤,若成功的話,可以得到下面截圖的結果。

也可以用網頁的方式查看目前HBase的狀態。其拜訪網址如下:


http://ip-address-or-domain-name:16010

總結

啟動HBase執行script順序如下:


start-hdfs.sh
start-yarn.sh

start-hbase.sh

結束HBase之script順序如下:


stop-hbase.sh

stop-dfs.sh
stop-yarn.sh

每個script檔案擺放路徑就不在此一一贅述,可以去先前的文章內容中找到相對應的script檔案路徑。

Hadoop + HBase對於硬體資源是很要求的。我在自租的VPS,太差的配備是跑不起來的。

以個人的經驗來說,CPU建議至少要再4core至6core才夠用,RAM大約在16G會比較好一點,我是在DigitalOcean上面跑起來的。選用的方案是6core+16G的Droplet方案。

參考資料

在Ubuntu 16.04中安裝Hadoop

前言

因為工作上的需要,需要建置HBase當做資料儲存的空間,而這個同樣也是一個No-SQL資料庫。至於什麼是No-SQL DB,則不在此文章的範圍內,可以自行去查詢了解。

在本篇文章中,會教導該如何在Ubuntu 16.04中,將Hadoop與HBase架設起來。

前置環境

下面則是列出所需要的環境。

  • 一台乾淨且裝有Ubuntu 16.04的主機

安裝Hadoop

在本章節中,教導使用者們一步一步的安裝好Hadoop,可能在這裡會問:我只需要HBase,但是一定要安裝Hadoop嘛?答案是肯定的,因為HBase這個資料庫是相依於Hadoop,因此需要先安裝好Hadoop,才可以安裝HBase。

第一步:登入主機

首先先使用ssh登入到我們的主機


ssh user-name@ip-address-or-domain-name

第二步:建立hadoop使用者

在建立Hadoop之前,需要先建立一個名為hadoop使用者給Hadoop使用。先使用下面指令建立一個使用者。


sudo useradd -m hadoop -s /bin/bash


接著為這個hadoop使用者設置一個密碼,注意:密碼會需要輸入兩次來做確認


sudo passwd hadoop

為了增加目錄權限操作方便,我們將hadoop這個使用者設定有root權限可以使用,設定方式如下指令:


sudo adduser hadoop sudo


到這裡,就把Hadoop需要的使用者建立完成了,記得使用下面指令切換使用者再進行下一步!


su hadoop

第三步:更新鏡像來源並安裝JAVA環境

在Ubuntu底下,安裝任何的套件前,我們都會使用下面的指令先更新好鏡像來源網址。


sudo apt-get update

sudo apt-get install default-jdk default-jre

安裝好JAVA環境之後,可以使用下面的指令做測試:


java -version

如下圖所示:

第四步:設定JAVA環境執行路徑

在本步驟中,需要設定JAVA_HOME環境變數。

先編輯在家目錄下面的.bashrc檔案。


vim ~/.bashrc

接著加入路徑,注意:路徑有可能不同,需要自己設定正確的相對應路徑


export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export PATH=$PATH:$JAVA_HOME/bin
# 設定後面所需要用到的Hadoop相關執行路徑

export HADOOP_HOME=/usr/local/hadoop
export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin

設定完成之後,再執行source指令將此環境變數載入。


source ~/.bashrc

接著可以使用,whereis java與java -version這兩個指令做驗證。


whereis java

java -version

其結果如下圖所示:

第五步:安裝Hadoop

我們這邊選用的是2.8.5的版本,使用wget指令來進行下載壓縮檔。


wget http://apache.mirror.gtcomm.net/hadoop/common/hadoop-2.8.5/hadoop-2.8.5.tar.gz

第六步

  • 解壓縮Hadoop壓縮檔到/usr/local資料夾
  • 切換資料夾至/usr/local
  • 將資料夾名稱重新命名
  • 將/usr/local/hadoop切換權限給hadoop使用者

sudo tar -zxf ~/hadoop-2.8.5.tar.gz

cd /usr/local

sudo mv ~/hadoop-2.8.5/ ./hadoop

sudo chown -R hadoop /usr/local/hadoop

第七步:驗證Hadoop是否可以運行

下面指令可以幫助我們驗證hadoop是否可以正常運行


cd /usr/local/hadoop

./bin/hadoop version

如果可以成功運行的話,如下面截圖所示:

第八步:偽分佈式Hadoop

Hadoop允許可以使用兩個分離的process運行,意思就是一個當NameNode一個當DataNode,同時讀取的是HDFS文件。

要修改成此模式需要修改core-site.xml與hdfs-site.xml這兩個設定檔案。

Hadoop設定文件是以XML格式,每個設定的property都有起始與結尾標籤,在標籤裡面放置的是設定值。

先開啟,core-site.xml檔案。


cd /usr/local/hadoop

vim ./etc/hadoop/core-site.xml

接著在<configuration></configuration>標籤之間插入下面的值。


<property>
<name>hadoop.tmp.dir</name>
<value>file:///usr/local/hadoop/tmp</value>
<description>Abase for other temporary directories.</description>
</property>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>

接著,修改hdfs-site.xml設定檔案


cd /usr/local/hadoop

vim ./etc/hadoop/hdfs-site.xml

一樣在<configuration>與</configuration>中加入:


<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///usr/local/hadoop/tmp/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///usr/local/hadoop/tmp/dfs/data</value>
</property>

設定完成後,接著就可以使用下面指令執行NameNode初始化。


cd /usr/local/hadoop

./bin/hdfs namenode -format

執行完成之後,可以注意到這兩行,若是一樣,則代表執行成功。

第九步:執行NameNode與DataNode process

使用下面的指令執行與啟動NameNode與DataNode process


cd /usr/local/hadoop

./sbin/start-dfs.sh

執行此process期間,會使用到ssh相關的登入,因次遇到yes就輸入yes。

遇到打密碼,就打hadoop使用者的密碼。

若在執行過程中出現「localhost: Error: JAVA_HOME is not set and could not be found.」等字樣,則需要在/usr/local/hadoop/etc/hadoop/hadoop-env.sh 底下設定JAVA_HOME環境變數


export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

設定完成之後,再執行一次:./sbin/start-dfs.sh就會成功了。其成功截圖畫面如下:

設定好之後,使用網路瀏覽器拜訪網址:http://ip-address-or-domain-name:50070,就可以看到運行的狀態頁面了。

第十步:啟動yarn

首先,先執行下面的指令,修改檔案名稱並進行mapred-site.xml編輯。


cd /usr/local/hadoop

mv ./etc/hadoop/mapred-site.xml.template ./etc/hadoop/mapred-site.xml

vim ./etc/hadoop/mapred-site.xml

接著在<configuration>與</configuration>中加入下面的設定標籤。


<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

接著設定yarn-site.xml設定檔。


cd /usr/local/hadoop

vim ./etc/hadoop/yarn-site.xml

在<configuration>與</configuration>標籤中加入下面的設定值。


<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

接著就可以啟動yarn了。當然,中間會打密碼執行。

執行下面指令來啟動,啟動完成之後,可以拜訪:http://ip-address-or-domain-name:8088/cluster來看目前所有的叢集(cluster)的狀態與資訊。


cd /usr/local/hadoop

./sbin/start-yarn.sh

# 啟動背景 web server 查看歷史運作紀錄

./sbin/mr-jobhistory-daemon.sh start historyserver

後記

  • 如果使用較低方案的VPS 方案做練習的話,會跑不起來,原因是因為RAM太小不夠。因此需要使用與這篇文章來設定swap來達到這個目的。
  • 有的時候ssh連線是使用非port number 22,因此需要使用到HADOOP_SSH_OPTS來設定port number。設定此環境變數在.bashrc檔案即可,記得使用source 重新載入此檔案。設定環境變數如下,22是我們可以修改的port number:
    export HADOOP_SSH_OPTS="-p 22"
    

參考資料

下一篇將介紹如何安裝:HBase