天天看點

大資料與機器學習:實踐方法與行業案例.1.2資料平台

<b>1.2資料平台</b>

<b></b>

資料平台是存放分析資料的平台,也是支援大多數資料分析和資料挖掘應用的底層平台,它使用了統一的資料清洗與處理規則,因而可以保證從基礎平台上輸出的資料内容是一緻的。

傳統的資料平台基本等同于大家熟悉的“資料倉庫”,但網際網路浪潮讓人們對資料采集、存儲和應用提出了越來越高的要求,傳統資料倉庫平台獨力難支,是以“現代化”的資料平台是多種資料庫産品的融合。圖1-3是一個精簡化的現代資料平台架構圖。

圖1-3 資料平台架構示意圖

現代的資料平台融合了傳統資料倉庫、大資料平台、mpp資料庫、nosql資料庫等多種資料産品,這些資料庫産品之間互為補充,組成統一的資料平台。

從傳統的關系型資料庫開始,資料庫産品逐漸細分,這些細分産品在特定場景中比傳統的關系型資料庫表現出了更好的性能。圖1-4展示了一些主流的資料庫産品,注意到有很多資料庫産品是“跨界”産品,例如,oracle同時屬于關系型、分析型、操作型三類資料庫。

圖1-4 資料庫産品圖冊

圖1-4可為資料庫選型提供參考。比如,如果希望尋找一款關系型資料庫,既可以作為資料倉庫底層資料庫使用,也可以作為生産應用系統的資料庫伺服器(即操作型資料庫)使用,那麼從圖1-4中可供選擇的有oracle、db2、sql server等。

如果你希望從大量資料中發現隐含的關系網絡,那麼圖1-4中的資料庫是一個很好的選擇,從圖1-4的graph小框中可以發現有spark graphx、infinitegraph、neo4j等可供選擇。

在一些大型企業的資料平台中,可能會出現teradata、greenplum、vertica的身影。這三種資料庫屬于mpp(massive parallel processing)資料庫。雖然它們屬于關系型資料庫,但它們采用了一種與傳統關系型資料庫不同的存儲方式,即列存儲方式(oracle、db2、sql server等使用行存儲方式)。這種列存儲方式在面對大規模資料時,能表現出更好的效率,比如建立列索引、并行處理、叢集操作等。

mpp資料庫的問題在于其高昂的價格,這對于很多小型企業來說是一個“緻命傷害”,目前國内使用該類産品的企業一般為大型企業。第1.2.4節會對mpp資料庫做進一步介紹。

nosql資料庫是伴随着網際網路應用中崛起的新星。通過簡化資料存取模式(相對rdbms而言),減少了資料庫管理系統(dbms)的附加開銷,專注于讀/寫效率的提升,非常适合對讀取速度要求較高,且對資料不一緻性有容忍的應用環境中。

歸為newsql資料庫之列的sql azure和mysql cluster是傳統關系型資料庫的雲計算版本。目前該類資料庫在國内企業的應用中尚不常見,但随着雲計算的普及,預計國内一些大型企業有可能選用newsql資料庫。

下面,我們對圖1-3中組成資料平台的各主要子產品分别進行介紹。

1.2.1 資料倉庫平台

傳統資料倉庫平台,大多是基于關系型資料庫搭建的。在windows伺服器平台上,一般選用sql server、oracle、db2、mysql資料庫中的一種或者兩種混合搭建。

在linux伺服器平台上,可選擇的資料庫有db2、oracle、mysql(雖然sql server正在準備釋出linux版本)。資料倉庫平台的模組化過程已經有了完善的理論基礎,并且目前市面上也有很多相關書籍,限于篇幅,本書不做詳細介紹。資料倉庫工程師可以參閱以下書籍。

《資料倉庫》(《building the data warehouse》),機械工業出版社。

《資料庫系統:資料庫與資料倉庫導論》(《database systems: introduction to databases and data warehouses》),機械工業出版社。

資料入口和出口

資料倉庫本質上是解決大批量資料的入口和出口問題(簡單來說,即資料寫入資料倉庫和從資料倉庫中讀取出來),并為大資料量的分析和應用提供基礎支援。通常,在資料倉庫設計時,雖然我們會盡其所能滿足各種經典範式理論,但卻忽略了一個簡單且緻命的問題:資料應該如何高效地進出資料倉庫平台,并且對其他應用盡量透明呢?

很多資料倉庫平台在運作初期看起來非常完美,但在持續運作一段時間後,各種問題逐漸顯現出來,如資料庫死鎖、作業運作緩慢、etl過程卡死等。這種現象總是伴随着資料量的增長、資料倉庫資料表的增加以及資料倉庫通路使用者的增加而出現,這是典型的資料入口和出口問題頑疾。

一個能夠長期穩定提供“順滑”資料服務的資料倉庫才是一個“好”的資料倉庫,而不僅僅是看這個資料倉庫在設計時采用了什麼資料庫産品、滿足了多少範式理論。

根據筆者的經驗,“好”的資料倉庫的入口和出口至少要關注兩條規則,即資料的更新規則和存儲規則。更新規則會影響資料的入口效率和出口效率,存儲規則主要影響資料的出口效率。

(1)資料的更新規則

實際場景中,一個資料庫中的資料表總是面臨資料加載(load)的問題。比如一張交易明細表,每天淩晨需要将昨日的交易明細資料插入進去;而一張賬戶資訊表,則需要将每天新增的賬戶資訊插入及将狀态改變的賬戶資訊更新。

歸納起來,資料的更新規則分為兩種:增量更新和全量更新。上面的交易明細表即是增量更新方式,每天将新增的資料插入;而賬戶資訊表則可以采用全量更新的方式,每天将最新的賬戶資訊表從資料源重新加載進來,并覆寫原有資料。圖1-5展示了這兩種更新方式。

圖1-5 增量更新與全量更新

需要明确的是,在資料倉庫中進行的資料更新一般是大資料量的資料更新,這與生産應用系統中的單條資料更新在處理方式上有很大的不同。在資料倉庫場景中你将會面臨百萬(條)或者千萬(條)級别的資料量,如果使用sql中的insert(或update)語句,則insert語句帶來的事務管理、日志記錄等會嚴重降低資料庫性能,并且整個插入過程的耗時巨大,導緻資料表長時間不可用。

通常在面臨大批量資料更新時,正确的做法是使用批量導入指令進行批量導入操作,并盡可能避免update操作。我們将在第2章詳細介紹批量導入指令。

但是使用批量導入指令面臨的主要問題是“部分送出”的問題,因為資料庫管理系統(dbms)通常不将批量導入指令置于dbms的事務控制範疇之中,這意味着整個批量導入過程并不驗證資料庫範式,也不記錄記錄檔,是以,如果批量導入中途出現異常,那麼之前導入的資料将無法復原。

比如,一個信用卡中心每天的交易明細資料有900萬條,在往交易明細表中批量導入該批資料的時候,由于網絡問題導緻資料庫連接配接中斷,此時500萬條記錄已經導入交易明細表中且無法復原,這就出現了“部分送出”問題。

這種情況是一個讓人郁悶的問題,因為必須将導入的500萬條資料删除(delete),然後重新運作批量導入指令。而從一個龐大的資料表中删除500萬條資料簡直是一種災難,相信經曆過的人肯定不想再來一次。

當全量更新時,除了“部分送出”的問題,還可能面臨“資料斷檔”的問題。因為在全量更新時,首先需要将原表中的資料清空,之後再将新資料批量導入至清空後的表中。從資料清空到新資料全部導入,這個過程即為“資料斷檔”,因為在這個過程中資料表是無法對外提供服務的。

“部分送出”和“資料斷檔”是資料倉庫運作過程中經常遇到的問題。一種可行的方案是增加中間表,即資料先完整導入中間表,然後再從中間表插入目标表,如圖1-6所示。

圖1-6 通過中間表進行批量加載

在圖1-6中,原來交易明細表的增量更新拆分為以下兩步。

1)清空“交易明細中間表”,并将t-1日交易資料全量更新至“交易明細中間表”中。

2)将“交易明細中間表”中的資料全部insert into到“交易明細表”中。

上述兩個步驟中,假設步驟1)出現問題,則清空“交易明細中間表”後重新執行步驟1);而如果步驟2)出現問題,則資料庫通過自動復原會将已經insert的資料復原掉,不會出現資料不完整的情況。

在圖1-6中,對于全量更新的賬戶表,拆分為以下三步完成。

1)清空“賬戶中間表”,并将t-1日賬戶資料全量更新至“賬戶中間表”。

2)drop掉原賬戶表(t-2日賬戶資料)。

3)将“賬戶中間表”重命名為“賬戶表”,實作資料切換。

上述三個步驟,規避了“部分送出”的問題,同時在資料加載至中間表的過程中,原“賬戶資訊表(t-2日資料)”仍可以正常提供資料服務(隻不過資料并不是那麼“新鮮”),是以解決了資料空檔期的問題。

通過中間表,上述的增量更新、全量更新出現問題後,可以簡單地通過重新執行解決,是以可以友善地通過程式自動完成上述過程。這種自動化過程規避了人工操作風險,降低了資料倉庫維護成本,使資料倉庫更加“順滑”。第3章将詳細介紹如何采用這種理念實作資料的增量更新和全量更新。

(2)資料的存儲規則

資料倉庫在運作初期一般都表現良好,這是因為運作初期的資料量、使用者數、作業數量等均比較少,資料伺服器本身的硬體性能可足以支撐這些業務。但是,随着資料量、使用者數、作業數量的逐漸增長,資料倉庫的運作效率會逐漸降低。需要運維人員通過技術手段進行持續優化(如分區、建立索引、優化作業腳本等)。除此之外,資料的存儲規則也是需要重點對待的事情。

對于一個每日增量更新的表,如上述交易明細表,其每天新增的資料量是非常驚人的,如某商業銀行信用卡每天交易資料達860萬條,這些資料每天導入到交易明細表中,每年的交易資料可以達到3tb左右,傳統關系型資料庫這種大表的檢索效率是非常低的,更不用說在這種大表上進行更新、删除等操作了。

經過分析發現,資料倉庫使用者使用的交易明細資料90%集中在近三個月,而60%的作業僅使用近一個月的交易資料。是以,可以将交易明細資料分表存儲,即一個月的交易資料存放在一個表中,并以月份為表名字尾,這樣每個月的交易明細資料僅為250gb,通過适當的索引優化,傳統關系型資料庫在數tb級别仍然可以支援90%的業務場景。

圖1-7中,原交易明細資料表按月拆分成小表,并使用yyyymm格式日期作為表名字尾。拆分成小表後,如果是通路最近一個月的交易明細資料,則直接通路表trx_dtl_yyyymm即可;而如果想通路最近三個月的交易資料,則通過視圖v_trx_dtl_r3m通路即可。這樣,在存儲空間幾乎不變的情況下,大幅度提高讀取效率,進而使整個資料倉庫的出口變得“順滑”;另外,按月存儲的交易明細表由于體積小,能更友善進行優化管理(如建立索引、遷移資料等),間接提高了資料倉庫的入口效率。

圖1-7 分表存儲

拆分成小表後,由于表的命名規則固定(原表名+月份字尾),是以整個拆分表以及組合成視圖的過程均可以通過腳本作業自動完成,提高了管理效率且節省了人力成本。

總體來說,在面對增量更新的“大表”時,資料的存儲規則是“大表拆小表,小表組視圖”,基本依據在于小表的通路效率高于大表的。

而對于全量更新的“大表”,也可以借鑒“大表拆小表”的方式。比如對于全量的賬戶資訊表,可以根據賬戶狀态将表分為多張小表,也可以根據賬戶号按一定的規則進行切分得到小表,總之需要根據實際情況,将大表切分成合适的小表,以提高通路效率。

盡管有諸多的優化方法,傳統資料倉庫在面臨大資料量的時候,仍然無法規避存儲空間和計算效率的問題,這要求我們在傳統資料倉庫解決方案之外尋求突破。

1.2.2 大資料平台

大資料的發展異常迅猛,各種開源或商用平台層出不窮,在選擇大資料産品的時候,應該本着務實的原則,從實際情況出發選擇真正需要的功能,畢竟技術的核心價值是幫助我們解決問題,一味追求新潮技術并不可取。

大資料平台的基礎是分布式:分布式存儲和分布式計算,它們分别用于解決單機資料庫面臨的兩大困境,即資料量的問題和計算效率的問題,如圖1-8所示。單機資料庫由于無法支援分布式,是以其存儲容量和計算能力的瓶頸難以突破,而大資料平台通過分布式擴充輕易解決了這兩個問題。

圖1-8 大資料平台的基礎:分布式

分布式與擴充性密不可分,當存儲和計算能力不足時,顯而易見的方案就是增加叢集中的機器,在存儲價格和cpu價格日益下降而人力成本日益上漲的今天,這比從優化傳統資料庫系統着手要簡單高效,且成本更低。這也是為什麼說“能通過增加機器解決的問題都不是問題”的原因。

目前實際應用中的大資料平台基本是以開源的hadoop平台為核心,不同廠商在此基礎上進行封裝和擴充,形成自己的産品線。比較知名的商用大資料平台産品有:cloudera 的cdh,華為的fusioninsight。

圖1-9為大資料平台的核心元件。其底層基礎子產品hdfs(hadoop distribute file system,hadoop分布式檔案系統)用于提供分布式存儲能力;mapreduce分布式計算架構用于提供分布式計算能力。hdfs可支援多種元件,包括hive資料倉庫、資料挖掘、流處理等,其外圍的zookeeper負責叢集之間的協作管理,使衆多的機器可以成為統一的叢集,flume和sqoop則是大資料平台資料的入口和出口,負責與其他系統的資料互動。

圖1-9 大資料平台的核心元件

需要注意的是,hadoop的核心子產品提供的是離線、批量的計算,本身并不适合強實時環境,這也是為什麼把hadoop歸為分析系統的原因。不過,很多實時計算的元件經常與hadoop結合使用,如spark、storm、mahout等,這使得擴充後的hadoop平台具備了一定的實時處理能力。

下面讓我們快速認識hadoop的核心元件。

1. hdfs

hdfs(hadoop distributed file system,hadoop分布式檔案系統)是hadoop平台的檔案基礎,就如windows環境的ntfs (new technology file system)、linux環境的ext檔案系統(extended file system)一樣。

你可能并不需要關心hdfs的技術細節,但需要了解hdfs的主要設計理念是針對超大檔案存儲(幾百mb~pb級别),一次寫入、多次讀取。它不适合用在低延遲的場景,也不适合存儲大量小檔案,這是因為hdfs檔案的中繼資料(檔案基本資訊,如檔案名稱、路徑、存放的datanode節點資訊等)是存放在namenode的記憶體中的,大量的小檔案會消耗namenode的記憶體,而且會影響mapreduce對檔案的處理效率。

建立在hdfs之上的hive資料倉庫也是針對大資料量的資料分析工具的,在資料量未達到一定規模時,hive并不能展現出效率優勢(在小資料量時,hive的效率遠低于傳統關系型資料庫的)。這裡有一個經驗值,當一個表中的資料達到數百gb的時候,使用關系型資料庫進行讀/寫、join、sum、group by等操作時會耗費大量時間,運作一段sql腳本可能需要數個小時,這時hive将展現出絕對的優勢。

可以使用hadoop shell指令進行hdfs檔案的互動式操作。hadoop shell指令與linux的shell指令非常相似,多數情況下隻需要在linux shell指令前加上“hadoop fs”即可。常用的指令列舉如表1-1所示。

表1-1 hadoop shell常用指令

hadoop shell指令 說 明

hadoop fs -cat uri 将路徑指定檔案的内容輸出到stdout

hadoop fs -cp uri [uri …] &lt;dest&gt; 将檔案從源路徑複制到目标路徑。這個指令允許有多個源路徑,此時目标路徑必須是一個目錄

hadoop fs -copyfromlocal &lt;localsrc&gt; uri 從本地檔案系統中複制單個或多個源路徑到hdfs檔案系統

hadoop fs -copytolocal uri &lt;localdst&gt; 從hdfs檔案系統中複制單個或多個源路徑到本地檔案系統

hadoop fs -rm uri [uri …] 删除指定的檔案。隻删除非空目錄和檔案

hadoop fs -rmr uri [uri …] 遞歸版本

hadoop fs -test -[ezd] uri -e 檢查檔案是否存在。如果存在,則傳回0

-z 檢查檔案是否是0位元組。如果是,則傳回0

-d 如果路徑是一個目錄,則傳回1;否則傳回0

表1-1中的這些指令可以友善我們操作hdfs中的檔案,第3章将使用java調用hadoop shell指令的方式實作多線程批量導入資料至hive資料倉庫。詳細的hadoop shell指令可通路官方網站:http://hadoop.apache.org/docs/r1.0.4/cn/hdfs shell.html。

2. maprecude

mapreduce是hadoop平台的分布式計算架構,采用“分而治之”的思想,把對大規模資料集的操作分發給多個節點共同完成,然後通過整合各個節點的中間結果,得到最終結果。

mapreduce是一個簡單易用的程式設計模型,這個模型包括兩個部分:map過程和reduce過程,由map和reduce兩個函數分别實作。

map函數接受一個鍵–值對,經過處理産生一組中間鍵–值對。mapreduce架構會将map函數産生的鍵–值對裡鍵相同的值傳遞給一個reduce函數。

reduce函數接受一個鍵及相關的一組值,将這組值進行合并産生一組規模更小的值(通常隻有一個或沒有值)。

深入了解mapreduce的實作方式,對了解大資料平台的設計理念很有幫助,雖然類sql語言hive已經代辦了mapreduce的大部分工作,但是本書建議讀者能夠了解mapreduce的原理和簡單實作,這樣對于深入了解大資料大有幫助。

關于mapreduce的更多内容可以參考《hadoop權威指南(第3版)》(《hadoop: the definitive guide,3rd edition》),清華大學出版社。

3. hbase

hbase是基于hdfs的列式存儲分布式資料庫,屬于nosql中的big tables範疇(見圖1-4)。hbase号稱“能夠提供高可靠性、高性能、列存儲、可伸縮、實時讀/寫的資料庫系統”,是以在一些時效要求相對較高的場景,會出現hbase應用的身影。

但是需要注意的是,hbase是基于hdfs檔案存儲的,而hdfs并不是針對低延時的場景設計的,是以hbase本身的實時性能并不高,是以它比較适用于“異步的、準實時、高次元”的場景中。在後面第三部分中介紹的“實時資料營銷平台”即使用了hbase作為資料存儲。

如果你已經對hbase比較了解,則可以跳過本節下面的内容。

(1)hbase的概念視圖與實體視圖

通過概念視圖和實體視圖,可以幫助我們快速了解hbase的列存儲模式。首先看一下hbase的概念視圖,如圖1-10所示。

圖1-10 hbase的概念視圖

從圖1-10中可以看到hbase的幾個關鍵概念,即row key、time stamp和column family。

row key是hbase的辨別行字段,相同的row key在資料邏輯上屬于同一行,圖1-10中的資料均屬于row key=“charles”這一行。

time stamp是hbase的時間戳,在寫入資料時自動記錄。是以hbase可以自動記錄列的曆史版本,在需要儲存曆史變動記錄的場景裡,這個特征非常有用。圖1-10中的finance:balance列即有三個版本t5、t3、t2,在讀取資料時,hbase預設讀取最新版本。

column family是hbase的列族,hbase按照列族組織實體存儲。每個列族可以随意增加列,是以hbase的列一般表示為“列族名稱:列名稱”方式。圖1-10中列族finance含有一個列html,寫作finance:balance;列族status含有兩個列,分别是weight和height。

在圖1-10的概念視圖裡,盡管表可以看成是一個稀疏的行的集合,但在實體上,它是按列族分列存儲的。圖1-11是hbase的實體視圖。

圖1-11 hbase的實體視圖

注意到圖1-10中的空白格在實體上是不存儲的,因為根本沒有必要存儲。是以,若要擷取t8時間的finance:balance,結果就是空;同樣,若擷取t5時間的status:height,結果也是空。

(2)hbase的讀/寫操作

hbase在實際應用中一般用作準實時分布式資料庫,在資料量較小的時候表現并不突出,但在資料量巨大時的點寫入和點查詢性能均高于關系型資料庫的。

hbase的另一個優勢在于,可以幾乎無限制地進行列的擴充,這非常适用于替代傳統關系資料庫的“大寬表”,是以用于客戶标簽體系(客戶會擁有成千上萬個的标簽,并且是一個非常稀疏的資料表)的存儲表是非常合适的,在後面第三部分的介紹中,将會使用hbase作為使用者标簽系統的資料表。

hbase表可以通過hbase shell進行互動讀/寫。代碼清單1-1的hbase shell腳本建立了一個hbase表,并向其中插入了資料,然後讀取了相關資訊。

更多關于hbase shell指令的使用方法可參考hbase官網。

代碼清單 1-1

#建立表clt_tag,兩個列族,即base_info和trx_info

create 'clt_tag','base_info','trx_info'

#往表clt_tag中插入資料,rowkey=10001,列族base_info增加一個列name,值為queziyang

put 'clt_tag','10001','base_info:name','queziyang'

#往表clt_tag中插入資料,rowkey=10001,列族base_info增加一個列age,值為31

put 'clt_tag','10001','base_info:age','31'

#往表clt_tag中插入資料,rowkey=10001,列族trx_info增加一個列total_amt,值為1500.3

put 'clt_tag','10001','trx_info:total_amt','1500.3'

#讀取clt_tag中rowkey=10001、列base_info:name的資料

    get 'clt_tag','10001','base_info:name'

(3)hbase的批量讀/寫

hbase适用于點讀/寫場景,在進行大批量資料操作的時候會面臨一些問題。同時,存在這樣一種情況:hbase用于點查詢資料庫,但是資料本身需要定期更新,例如每天晚上需要将數千萬條資料更新至hbase表中,以便第二天進行查詢。在後面第三部分介紹的實時客戶标簽系統中,就需要每天将更新後的使用者标簽批量導入至hbase表中,是以hbase面臨批量更新的問題。

由于hbase的更新等同于插入,是以批量更新方式即批量導入的方式。比較高效的批量更新操作,一般通過mapreduce程式直接生成hbase存儲檔案hfile,然後将生成的hfile加載到hbase表中。具體參閱第2章批量導入hbase的章節。

關于hbase的更詳細内容,可以參考《hbase權威指南》(《hbase: the definitive guide》),人民郵電出版社。

4. hive

hive是hadoop平台的資料倉庫工具,它将hdfs檔案直接映射為資料表,并提供類sql(hive sql,hql)語句進行資料表操作。hql在執行時轉化為mapreduce作業,在實際的資料批量操作場景中,hive可以完成絕大部分本來需要mapreduce程式完成的任務,是以hive的出現降低了mapreduce的使用成本,僅僅通過撰寫簡單的hql語句就可以享受到mapreduce的強大功能,如圖1-12所示。hive是使用hadoop大資料平台資料倉庫的必備技能。

hive作為大資料平台資料倉庫工具,同傳統資料倉庫平台一樣需要有統一的設計原則。在設計大資料平台資料倉庫系統時,可以借鑒傳統資料倉庫的設計理念,把hive表看成是關系型資料庫的表。

同傳統資料倉庫一樣,hive資料倉庫中表的資料加載同樣分為增量更新和全量更新的情況,但由于hive本身的分布式特點,其資料表的存放規則與傳統資料倉庫的有所不同。

(1)hive分區表與增量更新

hive資料倉庫與傳統關系型資料倉庫一樣,也需要解決資料的出口與入口問題,不過由于hive資料本身基于hdfs分布式存儲,是以我們更關注hive資料倉庫制定資料的更新規則。回憶關系型資料倉庫的更新規則:增量更新與全量更新,這兩條規則也可以用于hive資料倉庫。

圖1-12 hql轉為mapreduce作業

增量更新可以使用hive的分區表來“完美”解決。hive的分區表類似于關系資料庫的表分區,即根據分區鍵将資料分散在不同的分區(partition),通過并行讀取提高效率。hive的分區表可以友善指定每個分區的hdfs路徑,是以可以通過程式自動完成,代碼清單1-2給出的腳本作為示例建立了一個分區表,并指定了load_day作為分區鍵。

代碼清單 1-2

create table adobe_log_app(

id      int,

name   string,

age     int,

tel      string

)

partitioned by(load_day string)

row format delimited

fields terminated by '\t'

stored as textfile;

alter table adobe_log_app add partition (load_day='20150927')  location

'/hive/data/adobe_log_app/20150927';

 “alter”指令往表adobe_log_app中增加了一個分區,并通過location指定了該分區的hdfs路徑。顯然,通過程式隻需要将表名、分區鍵值作為參數傳入,即可以實作增量資料的自動加載,其過程如圖1-13所示。

圖1-13 hive增量更新過程

第3章将依據圖1-13所示的流程實作hive表的增量更新。

(2)hive外部表與全量更新

hive的全量更新可以使用hive外部表(external table)實作。hive外部表在建立表的時候會同時指定資料檔案路徑,該檔案路徑一般處于hive預設資料檔案路徑之外,這也是hive外部表名稱的由來。

hive外部表通過在建立表的腳本中指定external關鍵字和location關鍵字(指定資料檔案的存放路徑)實作,代碼清單1-3是建立外部表的示例腳本。

代碼清單 1-3

create  external table clt_act_info(

act_id         bigint,

act_typ      string,

limit            int,

...

stored as textfile

location '/hive/data/clt_act_info';

hive外部表進行全量更新時,分為三個步驟:①删除原資料所在的hdfs目錄(location所指目錄);②建立新的hdfs目錄(目錄的路徑與原目錄保持一緻);③将新資料檔案複制到新的hdfs目錄。圖1-14展示了其整個過程。

5. spark

spark是基于記憶體的類mapreduce通用并行架構,它擁有mapreduce所具有的優點,并且抛棄了mapreduce的檔案中轉功能,不需要讀/寫hdfs,是以spark能更好地适用于資料挖掘與機器學習等需要多次疊代的計算場景。

spark包含四大主要元件,即spark sql、spark streaming、mllib(machine learning)、graphx,如圖1-15所示。

圖1-14 利用hive外部表實作資料的全量更新

圖1-15 spark的主要元件

spark sql同hive sql一樣,都是類sql語言,spark sql是基于spark進行分布式計算的,而hive sql是基于mapreduce進行分布式計算的。由于spark計算架構是記憶體實作,是以理論上spark sql的速度要比hive sql的快,當然其對記憶體的要求也比hive sql的高。

spark streaming是spark的流資料處理元件,它将流式計算分解成一系列短小的批處理作業,也就是把輸入資料按照batch size(如1秒)分成一段一段的資料,對每一小段的資料進行處理,整個過程可以看成是一連串非常小的批處理過程。streaming流處理一般使用消息隊列(如kafka)作為輸入端,實時收取消息隊列中訂閱的消息并進行處理。spark streaming能夠與kafka完美對接,有興趣的讀者可以參閱官網文檔。

mllib是spark的機器學習元件,它提供協同過濾、回歸、聚類、分類、人工神經網絡等主流機器學習算法,這些算法都提供了api接口,可以友善通過java或python進行程式設計調用,是以非常容易結合大資料平台使用。

graphx是spark的圖計算和圖挖掘引擎,圖計算在目前的關系網絡分析中受到越來越多的重視。關系網絡涉及多個主體之間的複雜聯系,如果使用關系型資料庫或者主流的資料分析工具(如sas、r、python)實作對整個關系網絡的描述,已經是一件非常困難的事情,更不用說進一步的分析和計算了。graphx融合了圖并行以及資料并行的優勢,雖然與單純的計算機段的性能相比不如graphlab等的計算架構,但是如果從整個圖處理流水線的視角(圖建構、圖合并以及最終結果的查詢)看,那麼性能就具有明顯的優勢。另外,由于spark還提供了流處理、機器學習等元件,這為企業在建構大資料平台時提供了一站式服務,預計spark graphx的應用将在大資料平台中占據主導。後面的第三部分将使用graphx實作一個關系網絡案例。

1.2.3 mpp資料庫

mpp資料庫即大規模并行處理資料庫,它是一種分布式關系型資料庫。mpp資料庫繼承了傳統關系型資料庫的使用者友好的互動界面,同時提供了大資料平台具有的分布式存儲和計算的功能。

圖1-4中的greenplum和vertica即屬于mpp資料庫。greenplum号稱支援50pb(1pb=1000tb)級海量資料的存儲功能,目前國内的大衆點評、阿裡巴巴、華泰保險、中國遠洋等均使用了該産品。

vertica在facebook上的成功應用使得最近幾年在國内市場有了快速增長。vertica使用标準的sql語句,是以對于熟悉傳統關系型資料庫的使用者來說,學習成本非常低。另外vertica的架構非常适合雲計算,包括虛拟化、分布式多節點運作等,并且可以和hadoop/mapreduce內建,是以非常利于市場推廣,目前國内的招商銀行已經引入該産品。

mpp資料庫在架構上可以分為master-slave架構(這其實也是hadoop的架構)和share-nothing架構(無共享節點架構)兩種,如圖1-16所示。greenplum屬于master-slave架構,但其随後的産品可能轉換為無共享節點架構,vertica屬于無共享節點架構。

圖1-16 mpp的兩種架構

在master-slave架構中,master有可能成為系統瓶頸,但是master節點本身并不負責計算,僅用于slave節點之間的控制以及互動資料的轉發,是以在實際使用中,master成為瓶頸的場景并不常見。

在無共享節點架構中,各個處理單元都有自己私有的cpu、記憶體、硬碟等資源,不存在共享資源,各節點之間通過協定進行通信,各節點獨自處理自己的資料,處理後的結果可能向上層彙總或在節點間流轉。

mpp資料庫定位于高端資料分析市場,是以價格比較昂貴,且對硬體有特殊要求(例如teradata采用軟硬體一體銷售政策)。另外,雖然mpp資料庫一般都支援使用标準sql語句,但很多傳統關系型資料庫的功能并不完全支援(例如vertica本身沒有存儲過程)。是以,在建構資料平台時需要根據公司的實際情況設計合理的産品選型方案—讓需求選擇技術,而不是讓技術選擇需求。

1.2.4 nosql資料庫

nosql即not only sql,是對非關系型資料庫的泛稱(參考圖1-4)。nosql資料庫不遵循傳統關系型資料庫的acid原則,并且抛棄了磁盤存儲,轉而走向了記憶體存儲。nosql資料庫大多應用于分布式應用系統中。

相對于傳統關系型資料庫的acid理論,nosql理論基礎主要基于cap原則(也叫cap定理,見圖1-17)。cap定理中的c、a、p分别指 consistency(一緻性)、 availability(可用性)、partition tolerance(分區容錯性)。nosql理論對分布式系統中的三個特性進行了如下歸納。

1)一緻性(c)。一緻性被稱為原子對象,任何的讀/寫都應該看起來是“原子”的。寫後面的讀一定能讀到前面寫的内容,所有的讀/寫請求都好像被全局排序。

2)可用性(a)。對任何非失敗節點都應該在有限時間内給出請求的回應(請求的可終止性)。

3)分區容錯性(p)。允許節點之間丢失任意多的消息,當網絡分區發生時,節點之間的消息可能會完全丢失。

cap定理由eric brewer教授提出,并由lynch等人于2002年證明了brewer的猜想。cap定理告訴我們,一個分布式系統不可能同時滿足一緻性、可用性和分區容錯性這三個需求,最多隻能同時滿足兩個。

圖1-17 cap定理

根據cap定理,可以根據不同的應用場景選取其中的兩個作為設計方向。目前,nosql資料庫作為實時應用系統資料庫一般遵循ap原則。滿足ap原則的nosql資料庫一般采用key-value記憶體資料庫,如redis(參考圖1-4)。

但cap定理正在面臨諸多質疑。cap的概念定義比較模糊,而且cap沒有考慮不同的基礎架構、不同的應用場景、不同的網絡基礎和使用者需求,而c、a、p在這些不同場景中的含義可能完全不同,這種無差異化的定義直接導緻了概念的不明确,同時也成為cap被質疑的源頭。

不過,cap定理仍然有顯著的指導意義,它至少告訴我們在設計分布式系統和選擇nosql資料庫産品時需要考慮的基本方向,它還提醒我們分布式系統與傳統系統架構存在的差異性,你必須根據實際的應用慎重選擇分布式架構。