以下圖所示,mapreduce模式的主要思想是將自動分割要執行的問題(例如程序)拆解成map(映射)和reduce(化簡)的方式,流程圖以下圖1所示: 前端
在數據被分割後經過Map 函數的程序將數據映射成不一樣的區塊,分配給計算機機羣處理達到分佈式運算的效果,在經過Reduce 函數的程序將結果彙整,從而輸出開發者須要的結果。 node
MapReduce 借鑑了函數式程序設計語言的設計思想,其軟件實現是指定一個Map 函數,把鍵值對(key/value)映射成新的鍵值對(key/value),造成一系列中間結果形式的key/value 對,而後把它們傳給Reduce(規約)函數,把具備相同中間形式key 的value 合併在一塊兒。Map 和Reduce 函數具備必定的關聯性。函數描述如表1 所示: 程序員
MapReduce致力於解決大規模數據處理的問題,所以在設計之初就考慮了數據的局部性原理,利用局部性原理將整個問題分而治之。MapReduce集 羣由普通PC機構成,爲無共享式架構。在處理以前,將數據集分佈至各個節點。處理時,每一個節點就近讀取本地存儲的數據處理(map),將處理後的數據進行 合併(combine)、排序(shuffle and sort)後再分發(至reduce節點),避免了大量數據的傳輸,提升了處理效率。無共享式架構的另外一個好處是配合複製(replication)策 略,集羣能夠具備良好的容錯性,一部分節點的down機對集羣的正常工做不會形成影響。 數據庫
ok,你能夠再簡單看看下副圖,整幅圖是有關hadoop的做業調優參數及原理,圖的左邊是MapTask運行示意圖,右邊是ReduceTask運行示意圖: 編程
如上圖所示,其中map階段,當map task開始運算,併產生中間數據後並不是直接而簡單的寫入磁盤,它首先利用內存buffer來對已經產生的buffer進行緩存,並在內存buffer中 進行一些預排序來優化整個map的性能。而上圖右邊的reduce階段則經歷了三個階段,分別Copy->Sort->reduce。咱們能 明顯的看出,其中的Sort是採用的歸併排序,即merge sort。 後端
Hadoop 是一個實現了MapReduce 計算模型的開源分佈式並行編程框架,程序員能夠藉助Hadoop 編寫程序,將所編寫的程序運行於計算機機羣上,從而實現對海量數據的處理。 緩存
此外,Hadoop 還提供一個分佈式文件系統(HDFS)及分佈式數據庫(HBase)用來將數據存儲或部署到各個計算節點上。因此,你能夠大體認 爲:Hadoop=HDFS(文件系統,數據存儲技術相關)+HBase(數據庫)+MapReduce(數據處理)。Hadoop 框架如圖2 所示: 服務器
藉助Hadoop 框架及雲計算核心技術MapReduce 來實現數據的計算和存儲,而且將HDFS 分佈式文件系統和HBase 分佈式數據庫很好的融入到雲計算框架中,從而實現雲計算的分佈式、並行計算和存儲,而且得以實現很好的處理大規模數據的能力。 restful
Hadoop的組成部分 架構
咱們已經知道,Hadoop是Google的MapReduce一個Java實現。MapReduce是一種簡化的分佈式編程模式,讓程序自動分佈到一個 由普通機器組成的超大集羣上併發執行。Hadoop主要由HDFS、MapReduce和HBase等組成。具體的hadoop的組成以下圖:
由上圖,咱們能夠看到:
一、 Hadoop HDFS是Google GFS存儲系統的開源實現,主要應用場景是做爲並行計算環境(MapReduce)的基礎組件,同時也是BigTable(如HBase、 HyperTable)的底層分佈式文件系統。HDFS採用master/slave架構。一個HDFS集羣是有由一個Namenode和必定數目的 Datanode組成。Namenode是一箇中心服務器,負責管理文件系統的namespace和客戶端對文件的訪問。Datanode在集羣中通常是 一個節點一個,負責管理節點上它們附帶的存儲。在內部,一個文件其實分紅一個或多個block,這些block存儲在Datanode集合裏。以下圖所示 (HDFS體系結構圖):
二、 Hadoop MapReduce是一個使用簡易的軟件框架,基於它寫出來的應用程序可以運行在由上千個商用機器組成的大型集羣上,並以一種可靠容錯的方式並行處理上TB級別的數據集。
一個MapReduce做業(job)一般會把輸入的數據集切分爲若干獨立的數據塊,由 Map任務(task)以徹底並行的方式處理它們。框架會對Map的輸出先進行排序,而後把結果輸入給Reduce任務。一般做業的輸入和輸出都會被存儲 在文件系統中。整個框架負責任務的調度和監控,以及從新執行已經失敗的任務。以下圖所示(Hadoop MapReduce處理流程圖):
三、 Hive是基於Hadoop的一個數據倉庫工具,處理能力強並且成本低廉。
主要特色:
存儲方式是將結構化的數據文件映射爲一張數據庫表。提供類SQL語言,實現完整的SQL查詢功能。能夠將SQL語句轉換爲MapReduce任務運行,十分適合數據倉庫的統計分析。
不足之處:
採用行存儲的方式(SequenceFile)來存儲和讀取數據。效率低:當要讀取數據表某一列數據時須要先取出全部數據而後再提取出某一列的數據,效率很低。同時,它還佔用較多的磁盤空間。
因爲以上的不足,有人(查禮博士)介紹了一種將分佈式數據處理系統中以記錄爲單位的存儲結構變爲以列爲單位的存儲結構,進而減小磁盤訪問數量,提升查詢處 理性能。這樣,因爲相同屬性值具備相同數據類型和相近的數據特性,以屬性值爲單位進行壓縮存儲的壓縮比更高,能節省更多的存儲空間。以下圖所示(行列存儲 的比較圖):
四、 HBase
HBase是一個分佈式的、面向列的開源數據庫,它不一樣於通常的關係數據庫,是一個適合於非結構化數據存儲的數據庫。另外一個不一樣的是HBase基於列的而 不是基於行的模式。HBase使用和 BigTable很是相同的數據模型。用戶存儲數據行在一個表裏。一個數據行擁有一個可選擇的鍵和任意數量的列,一個或多個列組成一個 ColumnFamily,一個Fmaily下的列位於一個HFile中,易於緩存數據。表是疏鬆的存儲的,所以用戶能夠給行定義各類不一樣的列。在 HBase中數據按主鍵排序,同時表按主鍵劃分爲多個HRegion,以下圖所示(HBase數據表結構圖):
以下圖所示,即是hadoop的內部結構,咱們能夠看到,海量的數據交給hadoop處理後,在hadoop的內部中,正如上文所述:hadoop提供一 個分佈式文件系統(HDFS)及分佈式數據庫(Hbase)用來存儲或部署到各個計算點上,最終在內部採起mapreduce的模式對其數據進行處理,然 後輸出處理結果:
圖2-1 海量數據產品技術架構
如上圖所示,咱們能夠看到,海量數據產品技術架構,分爲如下五個層次,從上至下來看,它們分別是:數據源,計算層,存儲層,查詢層和產品層。咱們來一一瞭解這五層:
數據來源層。存放着交易數據。在數據源層產生的數據,經過DataX,DbSync和Timetunel準實時的傳輸到下面第2點所述的「雲梯」。
計算層。在這個計算層內,採用的是hadoop集羣,這個集羣,咱們暫且稱之爲雲梯,是計算層的主要組成部分。在雲梯上,系統天天會對數據產品進行不一樣的mapreduce計算。
存儲層。在這一層,採用了兩個東西,一個使MyFox,一個是Prom。MyFox是基於MySQL的分佈式關係型數據庫的集羣,Prom是基於 hadoop Hbase技術 的(讀者可別忘了,在上文第一部分中,我們介紹到了這個hadoop的組成部分之一,Hbase—在hadoop以內的一個分佈式的開源數據庫)的一個 NoSQL的存儲集羣。
查詢層。在這一層中,有一個叫作glider的東西,這個glider是以HTTP協議對外提供restful方式的接口。數據產品經過一個惟一的URL來獲取到它想要的數據。同時,數據查詢便是經過MyFox來查詢的。下文將具體介紹MyFox的數據查詢過程。
產品層。簡單理解,不做過多介紹。
MyFOX
MySQL的MyISAM引擎做爲底層的數據存儲引擎。且爲了應對海量數據,他們設計了分佈式MySQL集羣的查詢代理層-MyFOX。
以下圖所示,是MySQL的數據查詢過程:
圖2-2 MyFOX的數據查詢過程
在MyFOX的每個節點中,存放着熱節點和冷節點兩種節點數據。顧名思義,熱節點存放着最新的,被訪問頻率較高的數據;冷節點,存放着相對而來比較舊 的,訪問頻率比較低的數據。而爲了存儲這兩種節點數據,出於硬件條件和存儲成本的考慮,你固然會考慮選擇兩種不一樣的硬盤,來存儲這兩種訪問頻率不一樣的節點 數據。以下圖所示:
圖2-3 MyFOX節點結構
「熱節點」,選擇每分鐘15000轉的SAS硬盤,按照一個節點兩臺機器來計算,單位數據的存儲成本約爲4.5W/TB。相對應地,「冷數據」咱們選擇了每分鐘7500轉的SATA硬盤,單碟上可以存放更多的數據,存儲成本約爲1.6W/TB。
Prom
出於文章篇幅的考慮,本文接下來再也不過多闡述這個Prom了。以下面兩幅圖所示,他們分別表示的是Prom的存儲結構以及Prom查詢過程:
圖2-4 Prom的存儲結構
圖2-5 Prom查詢過程
glide的技術架構
圖2-6 glider的技術架構
在這一層-查詢層中,主要是基於用中間層隔離先後端的理念而考慮。Glider這個中間層負責各個異構表之間的數據JOIN和UNION等計算,而且負責隔離前端產品和後端存儲,提供統一的數據查詢服務。
緩存
除了起到隔離先後端以及異構「表」之間的數據整合的做用以外,glider的另一個不容忽視的做用即是緩存管理。咱們有一點須瞭解,在特定的時間段內,咱們認爲數據產品中的數據是隻讀的,這是利用緩存來提升性能的理論基礎。
在上文圖2-6中咱們看到,glider中存在兩層緩存,分別是基於各個異構「表」(datasource)的二級緩存和整合以後基於獨立請求的一級緩存。除此以外,各個異構「表」內部可能還存在本身的緩存機制。
圖2-7 緩存控制體系
圖2-7向咱們展現了數據魔方在緩存控制方面的設計思路。用戶的請求中必定是帶了緩存控制的「命令」的,這包括URL中的query string,和HTTP頭中的「If-None-Match」信息。而且,這個緩存控制「命令」必定會通過層層傳遞,最終傳遞到底層存儲的異構「表」模 塊。
緩存系統每每有兩個問題須要面對和考慮:緩存穿透與失效時的雪崩效應。
緩存穿透是指查詢一個必定不存在的數據,因爲緩存是不命中時被動寫的,而且出於容錯考慮,若是從存儲層查不到數據則不寫入緩存,這將致使這個不存在的數據 每次請求都要到存儲層去查詢,失去了緩存的意義。至於如何有效地解決緩存穿透問題,最多見的則是採用布隆過濾器(這個東西,在個人此篇文章中有介紹:), 將全部可能存在的數據哈希到一個足夠大的bitmap中,一個必定不存在的數據會被這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。
而在數據魔方里,用了一個更爲簡單粗暴的方法,若是一個查詢返回的數據爲空(不論是數據不存在,仍是系統故障),咱們仍然把這個空結果進行緩存,但它的過時時間會很短,最長不超過五分鐘。
二、緩存失效時的雪崩效應儘管對底層系統的衝擊很是可怕。但遺憾的是,這個問題目前並無很完美的解決方案。大多數系統設計者考慮用加鎖或者隊列的方式保證緩存的單線程(進程)寫,從而避免失效時大量的併發請求落到底層存儲系統上。
在數據魔方中,存過時機制理論上可以將各個客戶端的數據失效時間均勻地分佈在時間軸上,必定程度上可以避免緩存同時失效帶來的雪崩效應。