中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

用大白話告訴你小白都能看懂的Hadoop架構原理

2018-11-20    來源:raincent

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

Hadoop 是目前大數(shù)據(jù)領域最主流的一套技術體系,包含了多種技術,例如 HDFS(分布式文件系統(tǒng)),YARN(分布式資源調度系統(tǒng)),MapReduce(分布式計算系統(tǒng))等等。

 

 

有些朋友可能聽說過 Hadoop,但是卻不太清楚它到底是個什么東西,這篇文章就用大白話給各位闡述一下。

假如你現(xiàn)在公司里的數(shù)據(jù)都是放在 MySQL 里的,那么就全部放在一臺數(shù)據(jù)庫服務器上,我們就假設這臺服務器的磁盤空間有 2T 吧,大家先看下面這張圖。

 

 

現(xiàn)在問題來了,你不停的往這臺服務器的 MySQL 里放數(shù)據(jù),結果數(shù)據(jù)量越來越大了,超過了 2T 的大小了,現(xiàn)在咋辦?

你說,我可以搞多臺 MySQL 數(shù)據(jù)庫服務器,分庫分表啊!每臺服務器放一部分數(shù)據(jù)不就得了。如上圖所示!

好,沒問題,那咱們搞 3 臺數(shù)據(jù)庫服務器,3 個 MySQL 實例,然后每臺服務器都可以 2T 的數(shù)據(jù)。

現(xiàn)在我問你一個問題,所謂的大數(shù)據(jù)是在干什么?我們來說一下大數(shù)據(jù)最初級的一個使用場景。

假設你有一個電商網(wǎng)站,要把這個電商網(wǎng)站里所有的用戶在頁面和 App 上的點擊、購買、瀏覽的行為日志都存放起來分析。

你現(xiàn)在把這些數(shù)據(jù)全都放在了 3 臺 MySQL 服務器上,數(shù)據(jù)量很大,但還是勉強可以放的下。

某天早上,你的 Boss 來了。要看一張報表,比如要看每天網(wǎng)站的 X 指標、Y 指標、Z 指標,等等,二三十個數(shù)據(jù)指標。

好了,兄弟,現(xiàn)在你嘗試去從那些點擊、購買、瀏覽的日志里,通過寫一個 SQL 來分析出那二三十個指標試試看?

我跟你打賭,你絕對會寫出來一個幾百行起步,甚至上千行的超級復雜大 SQL。這個 SQL,你覺得他能運行在分庫分表后的 3 臺 MySQL 服務器上么?

如果你覺得可以的話,那你一定是不太了解 MySQL 分庫分表后有多坑,幾百行的大 SQL 跨庫 Join,各種復雜的計算,根本不現(xiàn)實。

所以說,大數(shù)據(jù)的存儲和計算壓根兒不是靠 MySQL 來搞的,因此 Hadoop、Spark 等大數(shù)據(jù)技術體系才應運而生。

本質上,Hadoop、Spark 等大數(shù)據(jù)技術,其實就是一系列的分布式系統(tǒng)。比如 Hadoop 中的 HDFS,就是大數(shù)據(jù)技術體系中的核心基石,負責分布式存儲數(shù)據(jù),這是啥意思?別急,繼續(xù)往下看。

HDFS 全稱是 Hadoop Distributed File System,是 Hadoop 的分布式文件系統(tǒng)。

它由很多機器組成,每臺機器上運行一個 DataNode 進程,負責管理一部分數(shù)據(jù)。

然后有一臺機器上運行了 NameNode 進程,NameNode 大致可以認為是負責管理整個 HDFS 集群的這么一個進程,它里面存儲了 HDFS 集群的所有元數(shù)據(jù)。

然后有很多臺機器,每臺機器存儲一部分數(shù)據(jù)!好,HDFS 現(xiàn)在可以很好的存儲和管理大量的數(shù)據(jù)了。

這時候你肯定會有疑問:MySQL 服務器不也是這樣的嗎?你要是這樣想,那就大錯特錯了。

這個事情不是你想的那么簡單的,HDFS 天然就是分布式的技術,所以你上傳大量數(shù)據(jù),存儲數(shù)據(jù),管理數(shù)據(jù),天然就可以用 HDFS 來做。

如果你硬要基于 MySQL 分庫分表這個事兒,會痛苦很多倍,因為 MySQL 并不是設計為分布式系統(tǒng)架構的,它在分布式數(shù)據(jù)存儲這塊缺乏很多數(shù)據(jù)保障的機制。

好,你現(xiàn)在用 HDFS 分布式存儲了數(shù)據(jù),接著不就是要分布式來計算這些數(shù)據(jù)了嗎?

對于分布式計算:

很多公司用 Hive 寫幾百行的大 SQL(底層基于 MapReduce)。

也有很多公司開始慢慢的用 Spark 寫幾百行的大 SQL(底層是 Spark Core 引擎)。

總之就是寫一個大 SQL,然后拆分為很多的計算任務,放到各個機器上去,每個計算任務就負責計算一小部分數(shù)據(jù),這就是所謂的分布式計算。

這個,絕對比你針對分庫分表的 MySQL 來跑幾百行大 SQL 要靠譜的多。

 

 

對于上述所說的分布式存儲與分布式計算,老規(guī)矩,同樣給大家來一張圖,大伙兒跟著圖來仔細捋一下整個過程。

HDFS 的 NameNode 架構原理

好了,前奏鋪墊完之后,進入正題。本文主要就是討論一下 HDFS 集群中的 NameNode 的核心架構原理。

NameNode 有一個很核心的功能:管理整個 HDFS 集群的元數(shù)據(jù),比如說文件目錄樹、權限的設置、副本數(shù)的設置,等等。

下面就用最典型的文件目錄樹的維護,來給大家舉例說明,我們看看下面的圖,F(xiàn)在有一個客戶端系統(tǒng)要上傳一個 1TB 的大文件到 HDFS 集群里

 

 

此時它會先跟 NameNode 通信,說:大哥,我想創(chuàng)建一個新的文件,它的名字叫“/usr/hive/warehouse/access_20180101.log”,大小是 1TB,你看行不?

然后 NameNode 就會在自己內存的文件目錄樹里,在指定的目錄下搞一個新的文件對象,名字就是“access_20180101.log”。

這個文件目錄樹不就是 HDFS 非常核心的一塊元數(shù)據(jù),維護了 HDFS 這個分布式文件系統(tǒng)中,有哪些目錄,有哪些文件,對不對?

但是有個問題,這個文件目錄樹是在 NameNode 的內存里的啊!這可坑爹了,你把重要的元數(shù)據(jù)都放在內存里,萬一 NameNode 不小心宕機了可咋整?元數(shù)據(jù)不就全部丟失了?

可你要是每次都頻繁的修改磁盤文件里的元數(shù)據(jù),性能肯定是極低的啊!畢竟這是大量的磁盤隨機讀寫!

沒關系,我們來看看 HDFS 優(yōu)雅的解決方案。每次內存里改完了,寫一條 edits log,元數(shù)據(jù)修改的操作日志存到磁盤文件里,不修改磁盤文件內容,就是順序追加,這個性能就高多了。

每次 NameNode 重啟的時候,把 edits log 里的操作日志讀到內存里回放一下,不就可以恢復元數(shù)據(jù)了?

大家順著上面的文字,把整個過程,用下面這張圖跟著走一遍:

 

 

但是問題又來了,那 edits log 如果越來越大的話,豈不是每次重啟都會很慢?因為要讀取大量的 edits log 回放恢復元數(shù)據(jù)!

所以 HDFS 說,我可以這樣子啊,我引入一個新的磁盤文件叫做 fsimage,然后呢,再引入一個 JournalNodes 集群,以及一個 Standby NameNode(備節(jié)點)。

每次 Active NameNode(主節(jié)點)修改一次元數(shù)據(jù)都會生成一條 edits log,除了寫入本地磁盤文件,還會寫入 JournalNodes 集群。

然后 Standby NameNode 就可以從 JournalNodes 集群拉取 edits log,應用到自己內存的文件目錄樹里,跟 Active NameNode 保持一致。

然后每隔一段時間,Standby NameNode 都把自己內存里的文件目錄樹寫一份到磁盤上的 fsimage,這可不是日志,這是完整的一份元數(shù)據(jù)。這個操作就是所謂的 checkpoint 檢查點操作。

然后把這個 fsimage 上傳到 Active NameNode,接著清空掉 Active NameNode 的舊的 edits log 文件,這里可能都有 100 萬行修改日志了!

然后 Active NameNode 繼續(xù)接收修改元數(shù)據(jù)的請求,再寫入 edits log,寫了一小會兒,這里可能就幾十行修改日志而已!

如果說此時,Active NameNode 重啟了,Bingo!沒關系,只要把 Standby NameNode 傳過來的 fsimage 直接讀到內存里,這個 fsimage 直接就是元數(shù)據(jù),不需要做任何額外操作,純讀取,效率很高!

然后把新的 edits log 里少量的幾十行的修改日志回放到內存里就 OK 了!

這個過程的啟動速度就快的多了!因為不需要回放大量上百萬行的 edits log 來恢復元數(shù)據(jù)了!如下圖所示。

 

 

此外,大家看看上面這張圖,現(xiàn)在咱們有倆 NameNode:

一個是主節(jié)點對外提供服務接收請求。

另外一個純就是接收和同步主節(jié)點的 edits log 以及執(zhí)行定期 checkpoint 的備節(jié)點。

大家有沒有發(fā)現(xiàn)!他們倆內存里的元數(shù)據(jù)幾乎是一模一樣的啊!所以呢,如果 Active NameNode 掛了,是不是可以立馬切換成 Standby NameNode 對外提供服務?

這不就是所謂的 NameNode 主備高可用故障轉移機制么!接下來大家再想想,HDFS 客戶端在 NameNode 內存里的文件目錄樹,新加了一個文件。

但是這個時候,人家要把數(shù)據(jù)上傳到多臺 DataNode 機器上去啊,這可是一個 1TB 的大文件!咋傳呢?

很簡單,把 1TB 的大文件拆成 N 個 block,每個 block 是 128MB。1TB = 1024GB = 1048576MB,一個 block 是 128MB,那么就是對應著 8192 個 block。

這些 block 會分布在不同的機器上管理著,比如說一共有 100 臺機器組成的集群,那么每臺機器上放 80 個左右的 block 就 OK 了。

但是問題又來了,那如果這個時候 1 臺機器宕機了,不就導致 80 個 block 丟失了?

也就是說上傳上去的 1TB 的大文件,會丟失一小部分數(shù)據(jù)啊。沒關系!HDFS 都考慮好了!

它會默認給每個 block 搞 3 個副本,一模一樣的副本,分放在不同的機器上,如果一臺機器宕機了,同一個 block 還有另外兩個副本在其他機器上呢!

大伙兒看看下面這張圖。每個 block 都在不同的機器上有 3 個副本,任何一臺機器宕機都沒事!還可以從其他的機器上拿到那個 block。

這下子,你往 HDFS 上傳一個 1TB 的大文件,可以高枕無憂了吧!

 

 

OK,上面就是大白話加上一系列手繪圖,給大家先聊聊小白都能聽懂的 Hadoop 的基本架構原理。

大規(guī)模集群下 Hadoop NameNode 如何承載每秒上千次的高并發(fā)訪問

上面我們已經(jīng)初步給大家解釋了 Hadoop HDFS 的整體架構原理,相信大家都有了一定的認識和了解。

下面我們來看看,如果大量客戶端對 NameNode 發(fā)起高并發(fā)(比如每秒上千次)訪問來修改元數(shù)據(jù),此時 NameNode 該如何抗住?

問題源起

我們先來分析一下,高并發(fā)請求 NameNode 會遇到什么樣的問題。

大家現(xiàn)在都知道了,每次請求 NameNode 修改一條元數(shù)據(jù)(比如說申請上傳一個文件,那么就需要在內存目錄樹中加入一個文件),都要寫一條 edits log。

包括如下兩個步驟:

寫入本地磁盤。
通過網(wǎng)絡傳輸給 JournalNodes 集群。

但是如果對 Java 有一定了解的同學都該知道多線程并發(fā)安全問題吧?

NameNode 在寫 edits log 時的第一條原則:必須保證每條 edits log 都有一個全局順序遞增的 transactionId(簡稱為 txid),這樣才可以標識出來一條一條的 edits log 的先后順序。

那么如果要保證每條 edits log 的 txid 都是遞增的,就必須得加鎖。

每個線程修改了元數(shù)據(jù),要寫一條 edits log 的時候,都必須按順序排隊獲取鎖后,才能生成一個遞增的 txid,代表這次要寫的 edits log 的序號。

好了,那么問題來了,大家看看下面的圖。如果每次都是在一個加鎖的代碼塊里,生成 txid,然后寫磁盤文件 edits log,網(wǎng)絡請求寫入 JournalNodes 一條 edits log,會咋樣?

 

 

不用說,這個絕對完蛋了!NameNode 本身用多線程接收多個客戶端發(fā)送過來的并發(fā)的請求,結果多個線程居然修改完內存中的元數(shù)據(jù)之后,排著隊寫 edits log!

而且你要知道,寫本地磁盤 + 網(wǎng)絡傳輸給 JournalNodes,都是很耗時的啊!性能兩大殺手:磁盤寫 + 網(wǎng)絡寫!

如果 HDFS 的架構真要是這么設計的話,基本上 NameNode 能承載的每秒的并發(fā)數(shù)量就很少了,可能就每秒處理幾十個并發(fā)請求處理撐死了!

HDFS 優(yōu)雅的解決方案

所以說,針對這個問題,人家 HDFS 是做了不少的優(yōu)化的!

首先大家想一下,既然咱們不希望每個線程寫 edits log 的時候,串行化排隊生成 txid + 寫磁盤 + 寫 JournalNode,那么是不是可以搞一個內存緩沖?

也就是說,多個線程可以快速的獲取鎖,生成 txid,然后快速的將 edits log 寫入內存緩沖。

接著就快速的釋放鎖,讓下一個線程繼續(xù)獲取鎖后,生成 id + 寫 edits log 進入內存緩沖。

然后接下來有一個線程可以將內存中的 edits log 刷入磁盤,但是在這個過程中,還是繼續(xù)允許其他線程將 edits log 寫入內存緩沖中。

但是這里又有一個問題了,如果針對同一塊內存緩沖,同時有人寫入,還同時有人讀取后寫磁盤,那也有問題,因為不能并發(fā)讀寫一塊共享內存數(shù)據(jù)!

所以 HDFS 在這里采取了 double-buffer 雙緩沖機制來處理!將一塊內存緩沖分成兩個部分:

其中一個部分可以寫入。

另外一個部分用于讀取后寫入磁盤和 JournalNodes。

大家可能感覺文字敘述不太直觀,老規(guī)矩,咱們來一張圖,按順序給大家闡述一下。

 

 

①分段加鎖機制 + 內存雙緩沖機制

首先各個線程依次第一次獲取鎖,生成順序遞增的 txid,然后將 edits log 寫入內存雙緩沖的區(qū)域 1,接著就立馬第一次釋放鎖了。

趁著這個空隙,后面的線程就可以再次立馬第一次獲取鎖,然后立即寫自己的 edits log 到內存緩沖。

寫內存那么快,可能才耗時幾十微妙,接著就立馬第一次釋放鎖了。所以這個并發(fā)優(yōu)化絕對是有效果的,大家有沒有感受到?

接著各個線程競爭第二次獲取鎖,有線程獲取到鎖之后,就看看,有沒有誰在寫磁盤和網(wǎng)絡?

如果沒有,好,那么這個線程是個幸運兒!直接交換雙緩沖的區(qū)域 1 和區(qū)域 2,接著第二次釋放鎖。這個過程相當快速,內存里判斷幾個條件,耗時不了幾微秒。

好,到這一步為止,內存緩沖已經(jīng)被交換了,后面的線程可以立馬快速的依次獲取鎖,然后將 edits log 寫入內存緩沖的區(qū)域 2,區(qū)域 1 中的數(shù)據(jù)被鎖定了,不能寫。

怎么樣,是不是又感受到了一點點多線程并發(fā)的優(yōu)化?

②多線程并發(fā)吞吐量的百倍優(yōu)化

接著,之前那個幸運兒線程,將內存緩沖的區(qū)域 1 中的數(shù)據(jù)讀取出來(此時沒人寫區(qū)域 1 了,都在寫區(qū)域 2),將里面的 edtis log 都寫入磁盤文件,以及通過網(wǎng)絡寫入 JournalNodes 集群。

這個過程可是很耗時的!但是沒關系啊,人家做過優(yōu)化了,在寫磁盤和網(wǎng)絡的過程中,是不持有鎖的!

因此后面的線程可以噼里啪啦的快速的第一次獲取鎖后,立馬寫入內存緩沖的區(qū)域 2,然后釋放鎖。

這個時候大量的線程都可以快速的寫入內存,沒有阻塞和卡頓!怎么樣?并發(fā)優(yōu)化的感覺感受到了沒有!

③緩沖數(shù)據(jù)批量刷磁盤 + 網(wǎng)絡的優(yōu)化

那么在幸運兒線程吭哧吭哧把數(shù)據(jù)寫磁盤和網(wǎng)絡的過程中,排在后面的大量線程,快速的第一次獲取鎖,寫內存緩沖區(qū)域 2,釋放鎖,之后,這些線程第二次獲取到鎖后會干嘛?

他們會發(fā)現(xiàn)有人在寫磁盤啊,兄弟們!所以會立即休眠 1 秒,釋放鎖。

此時大量的線程并發(fā)過來的話,都會在這里快速的第二次獲取鎖,然后發(fā)現(xiàn)有人在寫磁盤和網(wǎng)絡,快速的釋放鎖,休眠。

怎么樣,這個過程沒有人長時間的阻塞其他人吧!因為都會快速的釋放鎖,所以后面的線程還是可以迅速的第一次獲取鎖后寫內存緩沖!

Again!并發(fā)優(yōu)化的感覺感受到了沒有?

而且這時,一定會有很多線程發(fā)現(xiàn),好像之前那個幸運兒線程的 txid 是排在自己之后的,那么肯定就把自己的 edits log 從緩沖里寫入磁盤和網(wǎng)絡了。

這些線程甚至都不會休眠等待,直接就會返回后去干別的事情了,壓根兒不會卡在這里。這里又感受到并發(fā)的優(yōu)化沒有?

然后那個幸運兒線程寫完磁盤和網(wǎng)絡之后,就會喚醒之前休眠的那些線程。

那些線程會依次排隊再第二次獲取鎖后進入判斷,咦!發(fā)現(xiàn)沒有人在寫磁盤和網(wǎng)絡了!

然后就會再判斷,有沒有排在自己之后的線程已經(jīng)將自己的 edtis log 寫入磁盤和網(wǎng)絡了:

如果有的話,就直接返回了。

沒有的話,那么就成為第二個幸運兒線程,交換兩塊緩沖區(qū),區(qū)域 1 和區(qū)域 2 交換一下。

然后釋放鎖,自己開始吭哧吭哧的將區(qū)域 2 的數(shù)據(jù)寫入磁盤和網(wǎng)絡。

但是這個時候沒有關系啊,后面的線程如果要寫 edits log 的,還是可以第一次獲取鎖后立馬寫內存緩沖再釋放鎖。以此類推。

總結

這套機制還是挺復雜的,涉及到了分段加鎖以及內存雙緩沖兩個機制。

通過這套機制,NameNode 保證了多個線程在高并發(fā)的修改元數(shù)據(jù)之后寫 edits log 的時候,不會說一個線程一個線程的寫磁盤和網(wǎng)絡,那樣性能實在太差,并發(fā)能力太弱了!

所以通過上述那套復雜的機制,盡最大的努力保證,一個線程可以批量的將一個緩沖中的多條 edits log 刷入磁盤和網(wǎng)絡。

在這個漫長的吭哧吭哧的過程中,其他的線程可以快速的高并發(fā)寫入 edits log 到內存緩沖里,不會阻塞其他的線程寫 edits log。

所以,正是依靠以上機制,最大限度優(yōu)化了 NameNode 處理高并發(fā)訪問修改元數(shù)據(jù)的能力!

 

 

中華石杉:十余年 BAT 架構經(jīng)驗,一線互聯(lián)網(wǎng)公司技術總監(jiān)。帶領上百人團隊開發(fā)過多個億級流量高并發(fā)系統(tǒng),F(xiàn)將多年工作中積累下的研究手稿、經(jīng)驗總結整理成文,傾囊相授。微信公眾號:石杉的架構筆記(ID:shishan100)。

標簽: Mysql 安全 大數(shù)據(jù) 大數(shù)據(jù)技術 代碼 電商 電商網(wǎng) 電商網(wǎng)站 服務器 互聯(lián)網(wǎng) 互聯(lián)網(wǎng)公司 權限 數(shù)據(jù)庫 通信 網(wǎng)絡

版權申明:本站文章部分自網(wǎng)絡,如有侵權,請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:城市未來碎碎念

下一篇:除了冒泡排序,你知道Python內建的排序算法嗎?