1. 程式人生 > >hadoop、hbase、hive、spark分散式系統架構原理

hadoop、hbase、hive、spark分散式系統架構原理

全棧工程師開發手冊 (作者:欒鵬)

機器學習、資料探勘等各種大資料處理都離不開各種開源分散式系統,hadoop使用者分散式儲存和map-reduce計算,spark用於分散式機器學習,hive是分散式資料庫,hbase是分散式kv系統,看似互不相關的他們卻都是基於相同的hdfs儲存和yarn資源管理,

hadoop、spark、Hbase、Hive、hdfs簡介

Hbase:是一個nosql資料庫,和mongodb類似

hdfs:hadoop distribut file system,hadoop的分散式檔案系統

Hive:hive是基於Hadoop的一個數據倉庫工具,可以將結構化的資料檔案(或者非結構化的資料)對映為一張資料庫表,並提供簡單的sql查詢功能,可以將sql語句轉換為MapReduce任務進行執行。 其優點是學習成本低,可以通過類SQL語句快速實現簡單的MapReduce統計,不必開發專門的MapReduce應用,十分適合資料倉庫的統計分析。

使用Hive,就不用去寫MapReduce,而是寫sql語句就行了。

sqoop:sqoop是和Hive一起使用的。Sqoop(發音:skup)是一款開源的工具,主要用於在Hadoop(Hive)與傳統的資料庫(mysql、postgresql…)間進行資料的傳遞,可以將一個關係型資料庫(例如 : MySQL ,Oracle ,Postgres等)中的資料導進到Hadoop的HDFS中,也可以將HDFS的資料導進到關係型資料庫中。

使用sqoop匯入資料至hive常用語句 :
直接匯入hive表

     sqoop import --connect jdbc:postgresql://ip/db_name--username user_name  --table table_name  --hive-import -m 5 

內部執行實際分三部,1.將資料匯入hdfs(可在hdfs上找到相應目錄),2.建立hive表名相同的表,3,將hdfs上資料傳入hive表中

這裡寫圖片描述

分散式hadoop架構

hadoop分為幾大部分:yarn負責資源和任務管理、hdfs負責分散式儲存、map-reduce負責分散式計算

YARN資源任務排程

YARN總體上仍然是master/slave(主從)結構

ResourceManager是Master上一個獨立執行的程序,負責叢集統一的資源管理、排程、分配等等;NodeManager是Slave上一個獨立執行的程序,負責上報節點的狀態;App Master和Container是執行在Slave上的元件,負責應用程式相關事務,比如任務排程、任務監控和容錯等,Container是yarn中分配資源的一個單位,包涵記憶體、CPU等等資源,yarn以Container為單位分配資源。

YARN的基本架構 ,YARN的架構設計使其越來越像是一個雲作業系統,資料處理作業系統。

這裡寫圖片描述

從YARN的架構來看,它主要由ResourceManager、 NodeManager、ApplicationMaster 和 Container組成

(1)ResourceManager(RM)
RM是一個全域性的資源管理器,負責整個系統的 資源管理和分配。它主要由兩個元件構成:排程器(Schedule)和應用程式管理器(Application Manager, ASM)

YARN分層結構的本質是ResourceManager。這個實體控制整個叢集並管理應用程式向基礎計算資源的分配。ResourceManager將各個資源部分(計算、記憶體、頻寬等)精心安排給基礎NodeManager(YARN的每節點代理)。ResourceManager還與ApplicationMaster一起分配每個應用程式內每個任務所需的資源,與NodeManager一起啟動和監視它們的基礎應用程式。在此上下文中,ApplicationMaster承擔了以前的TaskTracker的一些角色,ResourceManager承擔了JobTracker的角色。

a)排程器(Scheduler)
排程器根據容量、佇列等限制條件(如每個佇列分配一定的資源,最多執行一定數量的作業等),將系統中的資源分配給各個正在執行的應用程式。該排程器是一個“純排程器”,它不再從事任何與具體應用程式相關的工作。,比如不負責監控或者跟蹤應用的執行狀態等,也不負責重新啟動因應用執行失敗或者硬體故障而產生的失敗任務,這些均交由應用程式相關的ApplicationMaster完成。排程器僅根據各個應用程式的資源需求進行資源分配,而資源分配單位用一個抽象概念“資源容器”(Resource Container,簡稱Container)表示,Container是一個動態資源分配單位,它將記憶體、CPU、磁碟、網路等資源封裝在一起,從而限定每個任務使用的資源量。此外,該排程器是一個可插拔的元件,使用者可根據自己的需要設計新的排程器,YARN提供了多種直接可用的排程器,比如Fair Scheduler和Capacity Scheduler等。

b)應用程式管理器(Application Manager,ASM)
應用程式管理器負責管理整個系統中所有的應用程式,包括應用程式提交、排程協調資源以啟動ApplicationMaster、監控ApplicationMaster執行狀態並在失敗時重新啟動它。

(2)ApplicationMaster(AM)

ApplicationMaster管理一個在YARN內執行的應用程式的每個例項。

ApplicationMaster負責申請而獲得的來自ResourceManager的資源,並通過NodeManager監視容器的執行和資源的使用(cpu、記憶體等資源分配)。

請注意,儘管目前的資源更加傳統(CPU核心、記憶體),但未來會帶來基於手頭任務的新資源型別(比如圖形處理單元,或專用處理裝置)。從YARN角度來講,ApplicationMaster使使用者程式碼因此存在潛在安全問題。YARN假設ApplicationMaster存在錯誤或者甚至是惡意的,因此將它們當做無特權的程式碼對待。

AM功能:資料切分、為應用程式申請資源並進一步分配給內部任務、任務監控與容錯

(3)NodeManager(NM)

NodeManager管理一個YARN叢集中的每個節點。NodeManager提供針對叢集中每個節點的服務,從監督對一個容器的終身管理到監視資源和跟蹤節點健康。MRv1通過插槽管理Map和Reduce任務執行,而NodeManager管理抽象容器,這些容器代表著可供一個特定應用程式使用的針對每個節點的資源。YARN繼續使用HDFS層。它的主要NameNode主要用於元資料服務,而DataNode用於分散在一個叢集中的複製儲存服務。
NM是每個節點上的資源和工作管理員。一方面,它會定時地向RM彙報本節點上的資源使用情況和各個Container執行狀態;另一方面,它接收並處理來自AM的 Container 啟動/停止等各種請求。

功能:單個節點上的資源管理和任務。處理來自於resourcemanager的命令。處理來自域ApplicationMaster的命令。

(4)Container
Container是YARN中的資源抽象,它封裝了某個節點上的多維度資源,如記憶體,CPU,磁碟,網路等。當AM向RM申請資源時,RM為AM返回的資源便是用Container表示的。YARN會為每個任務分配一個Container,且該任務只能用該Container中描述的資源。(注意:ApplicationMaster獲得的資源不一定是當前主機節點上的

應用程式在yarn上的排程流程

Client向ResourceManager提交的每一個應用程式都必須有一個Application Master,它經過ResourceManager分配資源後,運行於某一個Slave節點的Container中,每個應用程式包含多個任務task,每個任務同樣也執行在某一個Slave節點的Container容器中(不一定和Application Master在同一個Slave節點中)。RM,NM,AM乃至普通的Container之間的通訊,都是用RPC機制。

所以說:一個應用程式所需的Container分為兩大類,如下:

(1) 執行ApplicationMaster的Container:這是由ResourceManager(向內部的資源排程器)申請和啟動的,使用者提交應用程式時,可指定唯一的ApplicationMaster所需的資源;

(2) 執行各類任務的Container:這是由ApplicationMaster向ResourceManager申請的,並由ApplicationMaster與NodeManager通訊以啟動之。

以上兩類Container可能在任意節點上,它們的位置通常而言是隨機的,即ApplicationMaster可能不與它管理的任務執行在一個節點上。

所以ResourceManager接收到一個應用程式的客戶請求後,協商一個容器的必要資源,啟動一個ApplicationMaster來表示已經提交的應用程式。ApplicationMaster開始管理該應用程式的執行,也就是該應用程式內多個任務的執行。ApplicationMaster向ResourceManager請求每個任務所需的資源,ResourceManager分配處於多個節點撒上的資源後,ApplicationMaster協商每個節點上供該應程式使用的資源容器。執行應用程式時,ApplicationMaster監視資源容器,直到完成。當應用程式完成時,ApplicationMaster從ResourceManager登出其容器,執行週期就完成了。

YARN的工作原理

這裡寫圖片描述

來總結以下yarn的功能:

yarn的兩個部分:資源管理、任務排程。

資源管理需要一個全域性的ResourceManager(RM)和分佈在每臺機器上的NodeManager協同工作,RM負責資源的仲裁,NodeManager負責每個節點的資源監控、狀態彙報和Container的管理

任務排程也需要ResourceManager負責任務的接受和排程,在任務排程中,在Container中啟動的ApplicationMaster(AM)負責這個任務的管理,當任務需要資源時,會向RM申請,分配到的Container資源用來做任務,然後AM和這些Container做通訊,管理任務的執行,AM和具體執行的任務都是在Container中執行的。

一個應用程式的執行過程如下:

步驟1:使用者將應用程式提交到ResourceManager上;

步驟2:ResourceManager並與某個NodeManager通訊,在節點的container中啟動負責該應用程式的ApplicationMaster;

步驟3:ApplicationMaster與ResourceManager通訊,為內部要執行的任務(一個應用程式包含多個任務)申請資源,一旦得到資源後,將與NodeManager通訊,以啟動對應的任務。

步驟4:所有任務執行完成後,ApplicationMaster向ResourceManager登出,整個應用程式執行結束。

ApplicationMaster當向ResourceManager申請資源,需向它傳送一個ResourceRequest列表,其中,每個ResourceRequest描述了一個資源單元的詳細需求,而ResourceManager則為之返回分配到的資源描述Container。每個ResourceRequest可看做一個可序列化Java物件,包含的欄位資訊(直接給出了Protocol Buffers定義)如下:

    message ResourceRequestProto {

    optional PriorityProto priority = 1; // 資源優先順序

    optional string resource_name = 2; // 資源名稱(期望資源所在的host、rack名稱等)

    optional ResourceProto capability = 3; // 資源量(僅支援CPU和記憶體兩種資源)

    optional int32 num_containers = 4; // 滿足以上條件的資源個數

    optional bool relax_locality = 5 [default = true];  //是否支援本地性鬆弛(2.1.0-beta之後的版本新增加的,具體參考我的這篇文章:Hadoop新特性、改進、優化和Bug分析系列3:YARN-392)

    }

通過上面的資訊也看出了,資源不一定在當前主機上。可以為應用程式申請任意大小的資源量(CPU和記憶體),且預設情況下資源是本地性鬆弛的,即申請優先順序為10,資源名稱為“node11”,資源量為<2GB, 1cpu>的5份資源時,如果節點node11上沒有滿足要求的資源,則優先找node11同一機架上其他節點上滿足要求的資源,如果仍找不到,則找其他機架上的資源。而如果你一定要node11上的節點,則將relax_locality置為false。

發出資源請求後,資源排程器並不會立馬為它返回滿足要求的資源,而需要應用程式的ApplicationMaster不斷與ResourceManager通訊,探測分配到的資源,並拉取過來使用。一旦分配到資源後,ApplicatioMaster可從資源排程器那獲取以Container表示的資源,Container可看做一個可序列化Java物件,包含的欄位資訊(直接給出了Protocol Buffers定義)如下:

    message ContainerProto {

    optional ContainerIdProto id = 1; //container id

    optional NodeIdProto nodeId = 2; //container(資源)所在節點

    optional string node_http_address = 3;

    optional ResourceProto resource = 4; //container資源量

    optional PriorityProto priority = 5; //container優先順序

    optional hadoop.common.TokenProto container_token = 6; //container token,用於安全認證

    }

一般而言,每個Container可用於執行一個任務。ApplicationMaster收到一個或多個Container後,再次將該Container進一步分配給內部的某個任務,一旦確定該任務後,ApplicationMaster需將該任務執行環境(包含執行命令、環境變數、依賴的外部檔案等)連同Container中的資源資訊封裝到ContainerLaunchContext物件中,進而與對應的NodeManager通訊,以啟動該任務。ContainerLaunchContext包含的欄位資訊(直接給出了Protocol Buffers定義)如下:

    message ContainerLaunchContextProto {

    repeated StringLocalResourceMapProto localResources = 1; //Container啟動以來的外部資源

    optional bytes tokens = 2;

    repeated StringBytesMapProto service_data = 3;

    repeated StringStringMapProto environment = 4; //Container啟動所需的環境變數

    repeated string command = 5; //Container內部執行的任務啟動命令,如果是MapReduce的話,Map/Reduce Task啟動命令就在該欄位中

    repeated ApplicationACLMapProto application_ACLs = 6;

    }

每個ContainerLaunchContext和對應的Container資訊(被封裝到了ContainerToken中)將再次被封裝到StartContainerRequest中,也就是說,ApplicationMaster最終傳送給NodeManager的是StartContainerRequest,每個StartContainerRequest對應一個Container和任務。

hdfs分散式儲存架構

HDFS即Hadoop Distributed File System分散式檔案系統,它的設計目標是把超大資料集儲存到分佈在網路中的多臺普通商用計算機上,並且能夠提供高可靠性和高吞吐量的服務。分散式檔案系統要比普通磁碟檔案系統複雜,因為它要引入網路程式設計,分散式檔案系統要容忍節點故障也是一個很大的挑戰。

設計前提和目標

專為儲存超大檔案而設計:hdfs應該能夠支援GB級別大小的檔案;它應該能夠提供很大的資料頻寬並且能夠在叢集中拓展到成百上千個節點;它的一個例項應該能夠支援千萬數量級別的檔案。
適用於流式的資料訪問:hdfs適用於批處理的情況而不是互動式處理;它的重點是保證高吞吐量而不是低延遲的使用者響應
容錯性:完善的冗餘備份機制
支援簡單的一致性模型:HDFS需要支援一次寫入多次讀取的模型,而且寫入過程檔案不會經常變化
移動計算優於移動資料:HDFS提供了使應用計算移動到離它最近資料位置的介面
相容各種硬體和軟體平臺

不適合的場景

大量小檔案:檔案的元資料都儲存在NameNode記憶體中,大量小檔案會佔用大量記憶體。
低延遲資料訪問:hdfs是專門針對高資料吞吐量而設計的
多使用者寫入,任意修改檔案

hdfs架構設計

我們看一下hdfs的架構:hdfs部分由NameNode、SecondaryNameNode和DataNode組成。DataNode是真正的在每個儲存節點上管理資料的模組,NameNode是對全域性資料的名字資訊做管理的模組,SecondaryNameNode是它的從節點,以防掛掉。HSFS是以master/slave模式執行的,其中NameNode、SecondaryNameNode 執行在master節點,DataNode執行slave節點。

資料塊

磁碟資料塊是磁碟讀寫的基本單位,與普通檔案系統類似,hdfs也會把檔案分塊來儲存。hdfs預設資料塊大小為64MB,磁碟塊一般為512B,hdfs塊為何如此之大呢?塊增大可以減少定址時間與檔案傳輸時間的比例,若定址時間為10ms,磁碟傳輸速率為100MB/s,那麼定址與傳輸比僅為1%。當然,磁碟塊太大也不好,因為一個MapReduce通常以一個塊作為輸入,塊過大會導致整體任務數量過小,降低作業處理速度。

資料塊是儲存在DataNode中的,為了能夠容錯資料塊是以多個副本的形式分佈在叢集中的,副本數量預設為3,後面會專門介紹資料塊的複製機制。

hdfs按塊儲存還有如下好處:

檔案可以任意大,也不用擔心單個結點磁碟容量小於檔案的情況
簡化了檔案子系統的設計,子系統只儲存檔案塊資料,而檔案元資料則交由其它系統(NameNode)管理
有利於備份和提高系統可用性,因為可以以塊為單位進行備份,hdfs預設備份數量為3。
有利於負載均衡

NameNode

當一個客戶端請求一個檔案或者儲存一個檔案時,它需要先知道具體到哪個DataNode上存取,獲得這些資訊後,客戶端再直接和這個DataNode進行互動,而這些資訊的維護者就是NameNode。

NameNode管理著檔案系統名稱空間,它維護著檔案系統樹及樹中的所有檔案和目錄。NameNode也負責維護所有這些檔案或目錄的開啟、關閉、移動、重新命名等操作。對於實際檔案資料的儲存與操作,都是由DataNode負責。當一個客戶端請求資料時,它僅僅是從NameNode中獲取檔案的元資訊,而具體的資料傳輸不需要經過NameNode,是由客戶端直接與相應的DataNode進行互動。

NameNode儲存元資訊的種類有:

檔名目錄名及它們之間的層級關係
檔案目錄的所有者及其許可權
每個檔案塊的名及檔案有哪些塊組成

需要注意的是,NameNode元資訊並不包含每個塊的位置資訊,這些資訊會在NameNode啟動時從各個DataNode獲取並儲存在記憶體中,因為這些資訊會在系統啟動時由資料節點重建。把塊位置資訊放在記憶體中,在讀取資料時會減少查詢時間,增加讀取效率。NameNode也會實時通過心跳機制和DataNode進行互動,實時檢查檔案系統是否執行正常。不過NameNode元資訊會儲存各個塊的名稱及檔案由哪些塊組成。

一般來說,一條元資訊記錄會佔用200byte記憶體空間。假設塊大小為64MB,備份數量是3 ,那麼一個1GB大小的檔案將佔用163=48個檔案塊。如果現在有1000個1MB大小的檔案,則會佔用10003=3000個檔案塊(多個檔案不能放到一個塊中)。我們可以發現,如果檔案越小,儲存同等大小檔案所需要的元資訊就越多,所以,Hadoop更喜歡大檔案。

元資訊的持久化

在NameNode中存放元資訊的檔案是 fsimage。在系統執行期間所有對元資訊的操作都儲存在記憶體中並被持久化到另一個檔案edits中。並且edits檔案和fsimage檔案會被SecondaryNameNode週期性的合併

其它問題

執行NameNode會佔用大量記憶體和I/O資源,一般NameNode不會儲存使用者資料或執行MapReduce任務。

為了簡化系統的設計,Hadoop只有一個NameNode,這也就導致了hadoop叢集的單點故障問題。因此,對NameNode節點的容錯尤其重要,hadoop提供瞭如下兩種機制來解決:

  • 將hadoop元資料寫入到本地檔案系統的同時再實時同步到一個遠端掛載的網路檔案系統(NFS)。

  • 執行一個secondary NameNode,它的作用是與NameNode進行互動,定期通過編輯日誌檔案合併名稱空間映象,當NameNode發生故障時它會通過自己合併的名稱空間映象副本來恢復。需要注意的是secondaryNameNode儲存的狀態總是滯後於NameNode,所以這種方式難免會導致丟失部分資料(後面會詳細介紹)。

DataNode

DataNode是hdfs中的worker節點,它負責儲存資料塊,也負責為系統客戶端提供資料塊的讀寫服務,同時還會根據NameNode的指示來進行建立、刪除、和複製等操作。此外,它還會通過心跳定期向NameNode傳送所儲存檔案塊列表資訊。當對hdfs檔案系統進行讀寫時,NameNode告知客戶端每個資料駐留在哪個DataNode,客戶端直接與DataNode進行通訊,DataNode還會與其它DataNode通訊,複製這些塊以實現冗餘。

NameNode和DataNode架構圖

這裡寫圖片描述

SecondaryNameNode

需要注意,SecondaryNameNode並不是NameNode的備份。我們從前面的介紹已經知道,所有HDFS檔案的元資訊都儲存在NameNode的記憶體中。在NameNode啟動時,它首先會載入fsimage到記憶體中,在系統執行期間,所有對NameNode的操作也都儲存在了記憶體中,同時為了防止資料丟失,這些操作又會不斷被持久化到本地edits檔案中。

Edits檔案存在的目的是為了提高系統的操作效率,NameNode在更新記憶體中的元資訊之前都會先將操作寫入edits檔案。在NameNode重啟的過程中,edits會和fsimage合併到一起,但是合併的過程會影響到Hadoop重啟的速度,SecondaryNameNode就是為了解決這個問題而誕生的。

SecondaryNameNode的角色就是定期的合併edits和fsimage檔案,我們來看一下合併的步驟:

  • 合併之前告知NameNode把所有的操作寫到新的edites檔案並將其命名為edits.new。
  • SecondaryNameNode從NameNode請求fsimage和edits檔案
  • SecondaryNameNode把fsimage和edits檔案合併成新的fsimage檔案
  • NameNode從SecondaryNameNode獲取合併好的新的fsimage並將舊的替換掉,並把edits用第一步建立的edits.new檔案替換掉
  • 更新fstime檔案中的檢查點

最後再總結一下整個過程中涉及到NameNode中的相關檔案

  • fsimage :儲存的是上個檢查點的HDFS的元資訊
  • edits :儲存的是從上個檢查點開始發生的HDFS元資訊狀態改變資訊
  • fstime:儲存了最後一個檢查點的時間戳

MapReduce分散式計算架構

MapReduce特點:

  • 易於程式設計,使用者通常情況下只需要編寫Mapper和Reducer程式即可。
  • 良好的擴充套件性,即可以很容易的增加節點
  • 高容錯性,一個Job預設情況下會嘗試啟動兩次,一個mapper或者reducer預設會嘗試4次,如果一個節點掛了,可以向系統申請新的節點來執行這個mapper或者reducer
  • 適合PB級別的資料的離線處理

MapReduce框架的缺點

  • 不擅長實時計算,像MySQL一樣能夠立即返回結果
  • MapReduce的設計本身決定了處理的資料必須是離線資料,因為涉及到資料切分等等。
  • 不擅長DAG(有向圖)計算,需要一個Job執行完成之後,另一個Job才能使用他的輸出。

MapReduce程式設計模型:

一種分散式計算模型框架,解決海量資料的計算問題

MapReduce將整個平行計算過程抽象到兩個函式

  • Map(對映):對一些獨立元素組成的列表的每一個元素進行指定的操作,可以高度並行。
  • Reduce(化簡):對一個列表的元素進行合併。

例如wordcount功能:

Map階段:首先將輸入資料進行分片,然後對每一片資料執行Mapper程式,計算出每個詞的個數,之後對計算結果進行分組,每一組由一個Reducer程式進行處理,到此Map階段完成。
Reduce階段:每個Reduce程式從Map的結果中拉取自己要處理的分組(叫做Shuffling過程),進行彙總和排序(桶排序),對排序後的結果執行Reducer程式,最後所有的Reducer結果進行規約寫入HDFS。

一個簡單的MapReduce程式只需要指定map()、reduce()、input和output,剩下的事由架構完成。
input()——>map()——>reduce()——>output()

每個應用程式稱為一個作業(Job),每個Job由一系列的Mappers和Reducers來完成。 每個Mapper處理一個分片(Split),處理過程如下:

Map階段:

  • 輸入資料的解析:InputFormat
  • 輸入資料處理:Mapper
  • 輸入分組:Partitioner
  • 本節點的規約:Combiner ,

Reduce階段:

  • Shuffling階段拉取資料
  • 桶排序,是一個hash過程,使得相同的Key可以排在一堆
  • 資料規約:Reducer
  • 資料輸出格式: OutputFormat

MapReduce2.0 架構

這裡寫圖片描述

MapReduce2.0執行在YARN之上。YARN由ResourceManager(RM) 和NodeManager(NM)兩大塊組成。

MapReduce2 架構設計:
1:使用者向YARN中提交應用程式,其中包括ApplicationMaster程式、啟動ApplicationMaster的命令、使用者程式等。
2:ResourceManager為該應用程式分配第一個Container,並與對應的Node-Manager通訊,要求它在這個Container中啟動應用程式的ApplicationMaster。
3:ApplicationMaster首先向ResourceManager註冊,這樣使用者可以直接通過ResourceManage檢視應用程式的執行狀態,然後它將為各個任務申請資源,並監控它的執行狀態,直到執行結束,即重複步驟4~7。
4:ApplicationMaster採用輪詢的方式通過RPC協議向ResourceManager申請和領取資源。
5:一旦ApplicationMaster申請到資源後,便與對應的NodeManager通訊,要求它啟動任務。
6:NodeManager為任務設定好執行環境(包括環境變數、JAR包、二進位制程式等)後,將任務啟動命令寫到一個指令碼中,並通過執行該指令碼啟動任務。
7:各個任務通過某個RPC協議向ApplicationMaster彙報自己的狀態和進度,以讓ApplicationMaster隨時掌握各個任務的執行狀態,從而可以在任務失敗時重新啟動任務。在應用程式執行過程中,使用者可隨時通過RPC向ApplicationMaster查詢應用程式的當前執行狀態。

8:應用程式執行完成後,ApplicationMaster向ResourceManager登出並關閉自己。

MapReduce1 的架構設計:

Client: 客戶端
JobTracker : 主要負責 資源監控管理和作業排程。
a.監控所有TaskTracker 與job的健康狀況,一旦發現失敗,就將相應的任務轉移到其他節點;
b.同時JobTracker會跟蹤任務的執行進度、資源使用量等資訊,並將這些資訊告訴任務排程器,而排程器會在資源出現空閒時,選擇合適的任務使用這些資源.
TaskTracker: :是JobTracker與Task之前的橋樑
a.從JobTracker接收並執行各種命令:執行任務、提交任務、Kill任務、重新初始化任務;
b.週期性地通過心跳機制,將節點健康情況和資源使用情況、各個任務的進度和狀態等彙報給JobTracker
Task Scheduler: 任務排程器(預設 FIFO,先按照作業的優先順序高低,再按照到達時間的先後選擇被執行的作業)
Map Task: 對映任務
Reduce Task: 歸約任務

MapReduce例項——WordCount

問題:

有一批檔案(規模為TB級或者PB級),如何統計這些檔案中所有單詞出現的次數。

方案:

首先,分別統計每個檔案中單詞出現的次數。

然後,累加不同檔案中同一個單詞出現的次數。

MapReduce WordCount例項執行

在dfs中建立input目錄

[email protected] data]# hadoop fs -mkdir /wc/input

將data中的.data檔案拷貝到dfs中的input

[email protected] data]# hadoop fs -put ./*.data /wc/input

檢視

[email protected] data]# hadoop fs -ls /wc/input

執行wordcount

[email protected] hadoop-2.7.3]# hadoop jar hadoop-examples-1.2.1.jar wordcount /wc/input /wc/output

MapReduce基本流程

首先,將資料輸入到HDFS,再交給map,map對每個單詞進行統計

在map之後reduce之前進行排序

然後,將排好序的資料拷貝並進行合併,合併好的資料交給reduce,reduce再將完成的資料輸出回HDFS

這裡寫圖片描述
這裡寫圖片描述

MapReduce執行流程

Map任務處理

1,讀取輸入檔案內容,解析成key、value對。對輸入檔案的每一行,解析成key、value對。每一個鍵值對呼叫一次map函式。

2,寫自己的邏輯,對輸入的key、value處理,轉換成新的key、value輸出。

3,對輸出的key、value進行分割槽

4、對不同分割槽的資料,按照key進行排序、分組。相同key的value放到一個集合中。

5、(可選)分組後的資料進行歸約。

Reduce任務處理

1,對多個map任務的輸出,按照不同的分割槽,通過網路copy到不同的reduce節點。

2,對多個map任務的輸出進行合併、排序。寫reduce函式自己的邏輯,對輸入的key、value處理,轉換成新的key、value輸出。

3、把reduce的輸出儲存到檔案中。

編寫MapReduce程式

基於MapReduce計算模型編寫分散式並行程式非常簡單,程式設計師的主要編碼工作就是實現map和reduce函式。

MapReduce中,map和reduce函式遵循如下常規格式:

map:(K1,V1)——>list(K2,V2)
reduce:(K2,list(V2)) ——>list(K3,V3)

Mapper的介面:

protected void reduce(KEY key,Iterable<VALUE>values,Context context) throws IOException,interruptedException {

}

Reduce的介面:

protected void reduce(KEY key,Iterable<VALUE>values,Context context) throws IOException,interruptedException {

}

Spark相對於MapReduce的優勢

MapReduce存在的問題

  1. MapReduce框架侷限性

1)僅支援Map和Reduce兩種操作

2)處理效率低效。

a)Map中間結果寫磁碟,Reduce寫HDFS,多個MR之間通過HDFS交換資料; 任務排程和啟動開銷大;

b)無法充分利用記憶體

c)Map端和Reduce端均需要排序

3)不適合迭代計算(如機器學習、圖計算等),互動式處理(資料探勘) 和流式處理(點選日誌分析)

  1. MapReduce程式設計不夠靈活

1)嘗試scala函數語言程式設計語言

Spark

  1. 高效(比MapReduce快10~100倍)

1)記憶體計算引擎,提供Cache機制來支援需要反覆迭代計算或者多次資料共享,減少資料讀取的IO開銷

2)DAG引擎,減少多次計算之間中間結果寫到HDFS的開銷

3)使用多執行緒池模型來減少task啟動開稍,shuffle過程中避免 不必要的sort操作以及減少磁碟IO操作

  1. 易用

1)提供了豐富的API,支援Java,Scala,Python和R四種語言

2)程式碼量比MapReduce少2~5倍

  1. 與Hadoop整合 讀寫HDFS/Hbase 與YARN整合

spark應用執行機制分析

目前Apache Spark支援三種分散式部署方式,分別是standalone、spark on mesos和 spark on YARN還有最新的spark on k8s,其中,第一種類似於MapReduce 1.0所採用的模式,內部實現了容錯性和資源管理,後兩種則是未來發展的趨勢,部分容錯性和資源管理交由統一的資源管理系統完成:讓Spark執行在一個通用的資源管理系統之上,這樣可以與其他計算框架,比如MapReduce,公用一個叢集資源,最大的好處是降低運維成本和提高資源利用率(資源按需分配)。本文將介紹前三種部署方式,並比較其優缺點。 支援k8s原生的spark部署方式可以參考:https://blog.csdn.net/luanpeng825485697/article/details/83651742

1. Standalone模式

即獨立模式,自帶完整的服務,可單獨部署到一個叢集中,無需依賴任何其他資源管理系統。從一定程度上說,該模式是其他兩種的基礎。借鑑Spark開發模式,我們可以得到一種開發新型計算框架的一般思路:先設計出它的standalone模式,為了快速開發,起初不需要考慮服務(比如master/slave)的容錯性,之後再開發相應的wrapper,將stanlone模式下的服務原封不動的部署到資源管理系統yarn或者mesos上,由資源管理系統負責服務本身的容錯。目前Spark在standalone模式下是沒有任何單點故障問題的,這是藉助zookeeper實現的,思想類似於Hbase master單點故障解決方案。將Spark standalone與MapReduce比較,會發現它們兩個在架構上是完全一致的:

    1. 都是由master/slaves服務組成的,且起初master均存在單點故障,後來均通過zookeeper解決(Apache MRv1的JobTracker仍存在單點問題,但CDH版本得到了解決);
    1. 各個節點上的資源被抽象成粗粒度的slot,有多少slot就能同時執行多少task。不同的是,MapReduce將slot分為map slot和reduce slot,它們分別只能供Map Task和Reduce Task使用,而不能共享,這是MapReduce資源利率低效的原因之一,而Spark則更優化一些,它不區分slot型別,只有一種slot,可以供各種型別的Task使用,這種方式可以提高資源利用率,但是不夠靈活,不能為不同型別的Task定製slot資源。總之,這兩種方式各有優缺點。

流程:

1、使用SparkSubmit提交任務的時候(包括Eclipse或者其它開發工具使用new SparkConf()來執行任務的時候),Driver執行在Client;使用SparkShell提交的任務的時候,Driver是執行在Master上
2、使用SparkSubmit提交任務的時候,使用本地的Client類的main函式來建立sparkcontext並初始化它;
3、SparkContext連線到Master,註冊並申請資源(核心和記憶體)。
4、Master根據SC提出的申請,根據worker的心跳報告,來決定到底在那個worker上啟動StandaloneExecutorBackend(executor)
5、executor向SC註冊
6、SC將應用分配給executor,
7、SC解析應用,建立DAG圖,提交給DAGScheduler進行分解成stage(當出發action操作的時候,就會產生job,每個job中包含一個或者多個stage,stage一般在獲取外部資料或者shuffle之前產生)。然後stage(又稱為Task Set)被髮送到TaskScheduler。TaskScheduler負責將stage中的task分配到相應的worker上,並由executor來執行
8、executor建立Executor執行緒池,開始執行task,並向SC彙報
9、所有的task執行完成之後,SC向Master登出
這裡寫圖片描述

2. Spark On Mesos模式

這是很多公司採用的模式,官方推薦這種模式(當然,原因之一是血緣關係)。正是由於Spark開發之初就考慮到支援Mesos,因此,目前而言,Spark執行在Mesos上會比執行在YARN上更加靈活,更加自然。目前在Spark On Mesos環境中,使用者可選擇兩種排程模式之一執行自己的應用程式(可參考Andrew Xia的“Mesos Scheduling Mode on Spark”):

1) 粗粒度模式(Coarse-grained Mode):每個應用程式的執行環境由一個Dirver和若干個Executor組成,其中,每個Executor佔用若干資源,內部可執行多個Task(對應多少個“slot”)。應用程式的各個任務正式執行之前,需要將執行環境中的資源全部申請好,且執行過程中要一直佔用這些資源,即使不用,最後程式執行結束後,回收這些資源。舉個例子,比如你提交應用程式時,指定使用5個executor執行你的應用程式,每個executor佔用5GB記憶體和5個CPU,每個executor內部設定了5個slot,則Mesos需要先為executor分配資源並啟動它們,之後開始排程任務。另外,在程式執行過程中,mesos的master和slave並不知道executor內部各個task的執行情況,executor直接將任務狀態通過內部的通訊機制彙報給Driver,從一定程度上可以認為,每個應用程式利用mesos搭建了一個虛擬叢集自己使用。

2) 細粒度模式(Fine-grained Mode):鑑於粗粒度模式會造成大量資源浪費,Spark On Mesos還提供了另外一種排程模式:細粒度模式,這種模式類似於現在的雲端計算,思想是按需分配。與粗粒度模式一樣,應用程式啟動時,先會啟動executor,但每個executor佔用資源僅僅是自己執行所需的資源,不需要考慮將來要執行的任務,之後,mesos會為每個executor動態分配資源,每分配一些,便可以執行一個新任務,單個Task執行完之後可以馬上釋放對應的資源。每個Task會彙報狀態給Mesos slave和Mesos Master,便於更加細粒度管理和容錯,這種排程模式類似於MapReduce排程模式,每個Task完全獨立,優點是便於資源控制和隔離,但缺點也很明顯,短作業執行延遲大。

3. Spark On YARN模式

這是一種很有前景的部署模式。但限於YARN自身的發展,目前僅支援粗粒度模式(Coarse-grained Mode)。這是由於YARN上的Container資源是不可以動態伸縮的,一旦Container啟動之後,可使用的資源不能再發生變化,不過這個已經在YARN計劃中了。

spark on yarn 的支援兩種模式:
  1) yarn-cluster:適用於生產環境;
  2) yarn-client:適用於互動、除錯,希望立即看到app的輸出

yarn-cluster和yarn-client的區別在於yarn ApplicationMaster,每個yarn app例項有一個ApplicationMaster程序,是為app啟動的第一個container;負責從ResourceManager請求資源,獲取到資源後,告訴NodeManager為其啟動container。yarn-cluster和yarn-client模式內部實現還是有很大的區別。如果你需要用於生產環境,那麼請選擇yarn-cluster;而如果你僅僅是Debug程式,可以選擇yarn-client。

Spark執行模式列表(一定要熟悉!)

這裡寫圖片描述

注意: Spark on Yarn 有 yarn client 和 yarn clusters 模式。

Spark on Standalone 也有 standalone client 和 standalone clusters 模式。

yarn client流程

1、spark-submit指令碼提交,Driver在客戶端本地執行;
2、Client向RM申請啟動AM,同時在SC(client上)中建立DAGScheduler和TaskScheduler。
3、RM收到請求之後,查詢NM並選擇其中一個,分配container,並在container中開啟AM
4、client中的SC初始化完成之後,與AM進行通訊,向RM註冊,根據任務資訊向RM申請資源
5、AM申請到資源之後,與AM進行通訊,要求在它申請的container中開啟CoarseGrainedExecutorBackend(executor)。Executor在啟動之後會向SC註冊並申請task
6、SC分配task給executor,executor執行任務並向Driver(執行在client之上的)彙報,以便客戶端可以隨時監控任務的執行狀態
7、任務執行完成之後,client的SC向RM登出自己並關閉自己
這裡寫圖片描述

yarn cluster流程

1、spark-submit指令碼提交,向yarn(RM)中提交ApplicationMaster程式、AM啟動的命令和需要在Executor中執行的程式等
2、RM收到請求之後,選擇一個NM,在其上開啟一個container,在container中開啟AM,並在AM中完成SC的初始化
3、SC向RM註冊並請求資源,這樣使用者可以在RM中檢視任務的執行情況。RM根據請求採用輪詢的方式和RPC協議向各個NM申請資源並監控任務的執行狀況直到結束
4、AM申請到資源之後,與對應的NM進行通訊,要求在其上獲取到的Container中開啟CoarseGrainedExecutorBackend(executor),executor 開啟之後,向AM中的SC註冊並申請task
5、AM中的SC分配task給executor,executor執行task兵向AM中的SC彙報自己的狀態和進度
6、應用程式完成之後(各個task都完成之後),AM向RM申請登出自己兵關閉自己

在這裡插入圖片描述

HIVE和HBASE區別

Hive中的表是純邏輯表,就只是表的定義等,即表的元資料。Hive本身不儲存資料,它完全依賴HDFS和MapReduce。這樣就可以將結構化的資料檔案對映為為一張資料庫表,並提供完整的SQL查詢功能,並將SQL語句最終轉換為MapReduce任務進行執行。 而HBase表是物理表,適合存放非結構化的資料。

1. 兩者分別是什麼?

Apache Hive是資料倉庫。通過Hive可以使用HQL語言查詢存放在HDFS上的資料。HQL是一種類SQL語言,這種語言最終被轉化為Map/Reduce. 雖然Hive提供了SQL查詢功能,但是Hive不能夠進行互動查詢–因為它是基於MapReduce演算法。

Apache Hbase Key/Value,基礎單元是cell,它執行在HDFS之上。和Hive不一樣,Hbase的能夠在它的資料庫上實時執行,而不是執行MapReduce任務,。

2. 兩者的特點

Hive幫助熟悉SQL的人執行MapReduce任務。因為它是JDBC相容的。執行Hive查詢會花費很長時間,因為它會預設遍歷表中所有的資料。但可以通過Hive的分割槽來控制。因為這樣一來檔案大小是固定的,就這麼大一塊儲存空間,從固定空間裡查資料是很快的。

HBase通過儲存key/value來工作。注意版本的功能。

3. 限制

Hive目前不支援更新操作。另外,由於hive在hadoop上執行批量操作,它需要花費很長的時間,通常是幾分鐘到幾個小時才可以獲取到查詢的結果。Hive必須提供預先定義好的schema將檔案和目錄對映到列,並且Hive與ACID不相容。

HBase查詢是通過特定的語言來編寫的,這種語言需要重新學習。類SQL的功能可以通過Apache Phonenix實現,但這是以必須提供schema為代價的。另外,Hbase也並不是相容所有的ACID特性,雖然它支援某些特性。最後但不是最重要的–為了執行Hbase,Zookeeper是必須的,zookeeper是一個用來進行分散式協調的服務,這些服務包括配置服務,維護元資訊和名稱空間服務。

4. 應用場景

Hive適合用來對一段時間內的資料進行分析查詢,例如,用來計算趨勢或者網站的日誌。Hive不應該用來進行實時的查詢。因為它需要很長時間才可以返回結果。

Hbase非常適合用來進行大資料的實時查詢。Facebook用Hbase進行訊息和實時的分析。它也可以用來統計Facebook的連線數。

5. 總結

Hive和Hbase是兩種基於Hadoop的不同技術–Hive是一種類SQL的引擎,並且執行MapReduce任務,Hbase是一種在Hadoop之上的NoSQL 的Key/vale資料庫。當然,這兩種工具是可以同時使用的。就像用Google來搜尋,用FaceBook進行社交一樣,Hive可以用來進行統計查詢,HBase可以用來進行實時查詢,資料也可以從Hive寫到Hbase,設定再從Hbase寫回Hive。

HBASE架構

HBase由三個部分,如下

1. HMaster

對Region進行負載均衡,分配到合適的HRegionServer

2. ZooKeeper

選舉HMaster,對HMaster,HRegionServer進行心跳檢測(貌似是這些機器節點向ZooKeeper上報心跳)

3. HRegionServer

資料庫的分片,HRegionServer上的組成部分如下:

Region:HBase中的資料都是按row-key進行排序的,對這些按row-key排序的資料進行水平切分,每一片稱為一個Region,它有startkey和endkey,Region的大小可以配置,一臺RegionServer中可以放多個Region

CF:列族。一個列族中的所有列儲存在相同的HFile檔案中

HFile:HFile就是Hadoop磁碟檔案,一個列族中的資料儲存在一個或多個HFile中,這些HFile是對列族的資料進行水平切分後得到的。

MemStore:HFile在記憶體中的體現。當我們update/delete/create時,會先寫MemStore,寫完後就給客戶端response了,當Memstore達到一定大小後,會將其寫入磁碟,儲存為一個新的HFile。HBase後臺會對多個HFile檔案進行merge,合併成一個大的HFile

Hbase 架構的元件

  • Region Server:提供資料的讀寫服務,當客戶端訪問資料時,直接和Region Server通訊。
  • HBase Master:Region的分配,.DDL操作(建立表,刪除表)
  • Zookeeper:分散式管理工具,維護一個活躍的叢集狀態

Hadoop DataNode儲存著Region Server 管理的資料,所有的Hbase資料儲存在HDFS檔案系統中,Region Servers在HDFS DataNode中是可配置的,並使資料儲存靠近在它所需要的地方,就近服務,當王HBASE寫資料時是Local的,但是當一個region 被移動之後,Hbase的資料就不是Local的,除非做了壓縮(compaction)操作。NameNode維護物理資料塊的元資料資訊。

這裡寫圖片描述

Regions

HBase Tables 通過行健的範圍(row key range)被水平切分成多個Region, 一個Region包含了所有的,在Region開始鍵和結束之內的行,Regions被分配到叢集的節點上,成為 Region Servers,提供資料的讀寫服務,一個region server可以服務1000 個Region。

這裡寫圖片描述

三.HBase HMaster

分配Region,DDL操作(建立表, 刪除表)

協調各個Reion Server :

    -在啟動時分配Region、在恢復或是負載均衡時重新分配Region。

    -監控所有叢集當中的Region Server例項,從ZooKeeper中監聽通知。

管理功能:

    -提供建立、刪除、更新表的介面。

這裡寫圖片描述

ZooKeeper:協調器

Hbase使用Zookeeper作為分散式協調服務,來維護叢集中的Server狀態,ZooKeeper維護著哪些Server是活躍或是可用的。提供Server 失敗時的通知。Zookeeper使用一致性機制來保證公共的共享狀態,注意,需要使用奇數的三臺或是五臺機器,保證一致。

這裡寫圖片描述

元件之間如何工作

Zookeeper一般在分散式系統中的成員之間協調共享的狀態資訊,Region Server和活躍的HMaster通過會話連線到Zookeeper,ZooKeeper維護短暫的階段,通過心跳機制用於活躍的會話。

這裡寫圖片描述

每個Region Server建立一個短暫的節點,HMaster監控這些節點發現可用的Region Server,同時HMaster 也監控這些節點的伺服器故障。HMaster 通過撞見一個臨時的節點,Zookeeper決定其中一個HMaster作為活躍的。活躍的HMaster 給ZooKeeper傳送心跳資訊,不活躍的HMaster在活躍的HMaster出現故障時,接受通知。

如果一個Region Server或是一個活躍的HMaster在傳送心跳資訊時失敗或是出現了故障,則會話過期,相應的臨時節點將被刪除,監聽器將因這些刪除的節點更新通知資訊,活躍的HMaster將監聽Region Server,並且將會恢復出現故障的Region Server,不活躍的HMaster 監聽活躍的HMaster故障,如果一個活躍的HMaster出現故障,則不活躍的HMaster將會變得活躍。

Hbase META表

有一個特殊的Hbase 目錄表叫做Meta表,它擁有Region 在叢集中的位置資訊,ZooKeeper儲存著Meta表的位置。

表結構
在這裡插入圖片描述

我們來仔細分析一下這個結構,每條Row記錄了一個Region的資訊。

首先是RowKey,RowKey由三部分組成:TableName, StartKey 和 TimeStamp。RowKey儲存的內容我們又稱之為Region的Name。將組成RowKey的三個部分用逗號連線就構成了整個RowKey,這裡TimeStamp使用十進位制的數字字串來表示的.

然後是表中最主要的Family:info,info裡面包含三個Column:regioninfo, server, serverstartcode。其中regioninfo就是Region的詳細資訊,包括StartKey, EndKey 以及每個Family的資訊等等。server儲存的就是管理這個Region的RegionServer的地址。

所以當Region被拆分、合併或者重新分配的時候,都需要來修改這張表的內容。

META 表包含叢集中所有Region的列表

.META. 表像是一個B樹

.META. 表結構為:

  • Key: region start key,region id

  • Values: Region 和 RegionServer

這裡寫圖片描述

Hbase 的首次讀與寫

如下就是客戶端首次讀寫Hbase 所發生的事情:

現在假設我們要從Table2裡面插尋一條RowKey是RK10000的資料。那麼我們應該遵循以下步驟:

1.客戶端從Zookeeper查詢到meta表的位置,然後在Meta表中查詢哪個Region包含這條資料, 進而獲取管理這個Region的RegionServer地址。(每個Region Server管理著不同的Region),然後和Region Server進行通訊

2.客戶端將查詢 .META.伺服器,獲取它想訪問的相對應的Region Server的行健。客戶端將快取這些資訊以及META 表的位置。

3.客戶端將從相應的Region Server獲取行。

如果再次讀取,客戶端將使用快取來獲取META 的位置及之前的行健。這樣時間久了,客戶端不需要查詢META表,除非Region 移動所導致的丟失,這樣的話,則將會重新查詢更新快取。
這裡寫圖片描述

Region Server 的元件

Region Server 執行在HDFS DataNode上,並有如下元件:

WAL:Write Ahead Log 提前寫日誌是一個分散式檔案系統上的檔案,WAL儲存沒有持久化的新資料,用於故障恢復,類似Oracle 的Redo Log。

BlockCache:讀快取,它把頻繁讀取的資料放入記憶體中,採用LRU

MemStore:寫快取,儲存來沒有來得及寫入磁碟的新資料,每一個region的每一個列族有一個MemStore

Hfiles :儲存行,作為鍵值對,在硬碟上。

這裡寫圖片描述

Hbase 寫步驟1:

當客戶端提交一個Put 請求,第一步是把資料寫入WAL:

-編輯到在磁碟上的WAL的檔案,新增到WAL檔案的末尾

-WAL用於宕機恢復

這裡寫圖片描述

Hbase 寫步驟2

一旦資料寫入WAL,將會把它放到MemStore裡,然後將返回一個ACk給客戶端

這裡寫圖片描述

MemStore

MemStore 儲存以鍵值對的方式更新記憶體,和儲存在HFile是一樣的。每一個列族就有一個MemStore ,以每個列族順序的更新。
這裡寫圖片描述

HBase Region 重新整理(Flush)

當MemStore 積累到足夠的資料,則整個排序後的集合被寫到HDFS的新的HFile中,每個列族使用多個HFiles,列族包含真實的單元格,或者是鍵值對的例項,隨著KeyValue鍵值對在MemStores中編輯排序後,作為檔案重新整理到磁碟上。

注意列族是有數量限制的,每一個列族有一個MemStore,當MemStore滿了,則進行重新整理。它也會保持最後一次寫的序列號,這讓系統知道直到現在都有什麼已經被持久化了。

最高的序列號作為一個meta field 儲存在HFile中,來顯示持久化在哪裡結束,在哪裡繼續。當一個region 啟動後,讀取序列號,最高的則作為新編輯的序列號。

這裡寫圖片描述

HBase HFile

資料儲存在HFile,HFile 儲存鍵值,當MemStore 積累到足夠的資料,整個排序的鍵值集合會寫入到HDFS中新的HFile 中。這是一個順序的寫,非常快,能避免移動磁頭。

這裡寫圖片描述

HFile 的結構

HFile 包含一個多層的索引,這樣不必讀取整個檔案就能查詢到資料,多層索引像一個B+樹。

  • 鍵值對以升序儲存
  • 在64K的塊中,索引通過行健指向鍵值對的資料。
  • 每個塊有自己的葉子索引
  • 每個塊的最後的鍵被放入到一箇中間索引中。
  • 根索引指向中間索引。

trailer (追蹤器)指向 meta的塊,並在持久化到檔案的最後時被寫入。trailer 擁有 bloom過濾器的資訊以及時間範圍(time range)的資訊。Bloom 過濾器幫助跳過那些不含行健的檔案,時間範圍(time range)則跳過那些不包含在時間範圍內的檔案。

這裡寫圖片描述

HFile Index

索引是在HFile 開啟並放入記憶體中時被載入的,這允許在單個磁碟上執行查詢。

這裡寫圖片描述

HBase 讀合併

一個行的鍵值單元格可以被儲存在很多地方,行單元格已經被儲存到HFile中、在MemStore最近被更新的單元格、在Block cache最佳被讀取的單元格,所以當你讀取一行資料時,系統怎麼能把相對應的單元格內容返回呢?一次讀把block cache, MemStore, and HFiles中的鍵值合併的步驟如下:

1、首先,掃描器(scanner )在讀快取的Block cache尋找行單元格,最近讀取的鍵值快取在Block cache中,當記憶體需要時剛使用過的(Least Recently Used )將會被丟棄。
2、接下來,掃描器(scanner)將在MemStore中查詢,以及在記憶體中最近被寫入的寫快取。
3、如果掃描器(scanner)在MemStore 和Block Cache沒有找到所有的資料,則HBase 將使用 Block Cache的索引以及bloom過濾器把含有目標的行單元格所在的HFiles 載入到記憶體中。

這裡寫圖片描述

每個MemStore有許多HFiles 檔案,這樣對一個讀取操作來說,多個檔案將不得不被多次檢查,勢必會影響效能,這種現象叫做讀放大(read amplification)。

這裡寫圖片描述

HBase 輔壓縮(minor compaction)

HBase將會自動把小HFiles 檔案重寫為大的HFiles 檔案,這個過程叫做minor compaction。

輔助壓縮減少檔案的數量,並執行合併排序。

這裡寫圖片描述

HBase 主壓縮(Major Compaction)

主壓縮將會合並和重寫一個region 的所有HFile 檔案,根據每個列族寫一個HFile 檔案,並在這個過程中,刪除deleted 和expired 的單元格,這將提高讀效能。

然而因為主壓縮重寫了所有的檔案,這個過程中將會導致大量的磁碟IO操作以及網路擁堵。我們把這個過程叫做寫放大(write amplification)。

這裡寫圖片描述

Region = 臨近的鍵

  • 一個表將被水平分割為一個或多個Region,一個Region包含相鄰的起始鍵和結束鍵之間的行的排序後的區域。
  • 每個region預設1GB
  • 一個region的表通過Region Server 向客戶端提供服務
  • 一個region server可以服務1000 個region

這裡寫圖片描述

Region 分裂

初始時一個table在一個region 中,當一個region 變大之後,將會被分裂為2個子region,每個子Region 代表一半的原始Region,在一個相同的 Region server中並行開啟。

然後把分裂報告給HMaster。因為需要負載均衡的緣故,HMaster 可能會排程新的Region移動到其他的Server上。

這裡寫圖片描述

讀負載均衡(Read Load Balancing)

分裂一開始發生在相同的region server上,但是由於負載均衡的原因。HMaster 可能會排程新的Region被移動到其他的伺服器上。

導致的結果是新的Region Server 提供資料的服務需要讀取遠端的HDFS 節點。直到主壓縮把資料檔案移動到Regions server本地節點上,Hbase資料當寫入時是本地的,

但是當一個region 移動(諸如負載均衡或是恢復操作等),它將不會是本地的,直到做了主壓縮的操作(major compaction.)

這裡寫圖片描述

HDFS資料複製

所有的讀寫操作發生在主節點上,HDFS 複製WAL和HFile 塊,HFile複製是自動發生的,HBase 依賴HDFS提供資料的安全,

當資料寫入HDFS,本地化地寫入一個拷貝,然後複製到第二個節點,然後複製到第三個節點。

WAL 檔案和 HFile檔案通過磁碟和複製進行持久化,那麼HBase怎麼恢復還沒來得及進行持久化到HFile中的MemStore更新呢?

這裡寫圖片描述

這裡寫圖片描述

HBase 故障恢復

當一個RegionServer 掛掉了,壞掉的Region 不可用直到發現和恢復的步驟發生。Zookeeper 決定節點的失敗,然後失去region server的心跳。

然後HMaster 將會被通知Region Server已經掛掉了。

當HMaster檢查到region server已經掛掉後,HMaster 將會把故障Server上的Region重寫分配到活躍的Region servers上。

為了恢復宕掉的region server,memstore 將不會重新整理到磁碟上,HMaster 分裂屬於region serv