生產上的NameNode堆記憶體估算

2021-10-05 16:19:41 字數 4316 閱讀 6533

在hdfs中,資料和元資料是分開儲存的,資料檔案被分割成若干個資料塊,每乙個資料塊預設備份3份,然後分布式的儲存在所有的datanode上,元資料會常駐在namenode的記憶體中,而且隨著資料量的增加,在namenode中記憶體的元資料的大小也會隨著增加,那麼這個時候對namenode的記憶體的估算就變的非常的重要了。

這裡說的記憶體就是指namenode所在jvm的堆記憶體

namenode記憶體資料結構非常豐富,除了namespace tree和blocksmap外,其實還包括如leasemanager/snapshotmanager/cachemanager/networktopology等管理的資料,但是這些管理資料占用的記憶體非常的小,我們在估算namenode記憶體的時候一般都忽略這些資料所佔記憶體大小。所以在namenode記憶體中,主要的記憶體分別被namespace tree和blocksmap占有,那麼我們只要估算namespace tree和blocksmap所佔記憶體即可。

我們在namespace tree中估算了假設hdfs目錄和檔案數分別為1億,block總量在1億情況下,整個namespace在jvm中記憶體使用情況:

total

(directory)=(

8+72+

80) ∗ 100m +

8 ∗ num

(total children)

total

(files)=(

8+72+

56) ∗ 100m +

8 ∗ num

(total blocks)

記憶體總大小是:total

(directory)

+total

(files)=(

8+72+

80) ∗ 100m +8*

200m +(8

+72+56

) ∗ 100m +8*

100m =

31.25g

我們在blocksmap中估算了假設集群中共1億block,namenode可用記憶體空間固定大小128gb,則blocksmap占用記憶體情況:

blocksmap直接記憶體大小 +

(block直接記憶體大小 + blockinfocontiguous直接記憶體大小)

*100m + lightweightgset直接記憶體大小

28位元組 +

(40位元組 +

136位元組)

*100m +

60位元組 +(2

%*128g)

=19.7475gb

那麼綜上,假設整個hdfs集群中目錄和檔案數分別為1億,block總量在1億情況下,namenode可用記憶體空間固定大小128gb,總共占用的記憶體為:

namespace tree所佔記憶體大小 + blocksmap所佔記憶體大小 =

31.25g +

19.7475gb =

50.9975gb

在namenode記憶體其實主要的就是儲存著兩種型別的物件,乙個是file物件,乙個是block物件。

從namespace tree中我們可以得到:

乙個file物件的大小大概為:8 + 72 + 56 = 136位元組

乙個directory物件的大小大概為:8 + 72 + 80 = 160位元組

從blocksmap中我們可以得到:

乙個block物件的大小大概為:40位元組 + 136位元組 = 176位元組

為了方便計算,我們現在假設不管是file物件還是block物件,他們每乙個占用的記憶體大約為150位元組。

假設現在有乙個192mb的檔案,資料塊的大小是預設的128m,那麼這個192mb的檔案會被切分成兩個資料塊,乙個資料塊的大小是128mb,另乙個資料塊的大小是64mb。就會有3個物件(1個file物件和2個block物件)存在於namenode的記憶體中,占用的記憶體的大小大約為 3 * 150位元組 = 450位元組。

大檔案被切分成的資料塊越少,那麼占用namenode的記憶體就越少。比如乙個128mb大小檔案被切分成乙個資料塊的時候占用的記憶體大約是300位元組(乙個file物件和乙個block物件);相反,128個1mb的檔案在namenode的記憶體中會產生256個物件(128個file物件 + 128個block物件),這樣的話則會占用256 * 150位元組 = 38400位元組的記憶體

我們知道hdfs的資料塊的預設的備份數是3,我們需要知道的是備份數的設定會影響磁碟容量而不會影響namenode中記憶體容量

如果我們現在設定備份數為1,資料塊的大小是128mb。那麼乙個192mb的檔案需要集群的192mb大小的磁碟容量和450位元組的記憶體容量;假設有192tb的資料,這些資料報括了一百萬檔案和兩百萬資料塊,那麼需要集群的192tb磁碟容量和(一百萬file物件 + 兩百萬block物件) * 150位元組 = 450mb的記憶體容量。

當我們設定備份數為預設備份數(即3)的時候,對於192tb的資料,需要集群的192 tb * 3 = 576 tb的磁碟容量,但是需要的namenode中的記憶體容量還是450mb。所以說namenode中的記憶體大小和備份數多少關係並不是太大

接下來我們看下兩個估算namenode記憶體的例子,在看這兩個例子之前,我們先記住乙個經驗值:每一百萬個block需要namenode的1g記憶體。

上面的是乙個經驗值,你可以按照一百萬個block伴隨著有一百萬個檔案和一百萬個目錄來進行估算下,不管怎麼樣,這個是乙個比較靠譜的經驗者,我們可以使用這個經驗值進行估算我們的集群需要多少namenode的記憶體

假設有1gb(1024mb)的資料,我們將它切分成不同數量檔案和資料塊(資料塊大小為128m),然後分別來看下namenode需要消耗多少記憶體:

乙個 1gb 的檔案

1個file物件

8個block物件(1024mb / 128m)

total = 9個物件 * 150位元組 = 1350 bytes

8個檔案,每個檔案128mb

8個file物件

8個block物件

total = 16個物件 * 150位元組 = 2400位元組

1024個1mb的檔案

1024個file物件

1024個block物件

total = 2048個物件 * 150位元組 = 307200位元組

在這個例子中,我們假設有兩個hdfs集群,兩個集群的總磁碟容量都是4800 tb。其中集群a的資料塊的備份數設定為1,集群b的資料塊的備份數設定為3;兩個集群的資料塊大小都是128m。那麼兩個集群的namenode分別需要的最大的堆記憶體是多少呢?

集群a:200臺主機,每台主機的磁碟容量是24 tb,總共的磁碟容量大小是4800 tb

資料塊大小是128m,備份數是1

集群的磁碟容量:200*24

,000

,000 mb =4,

800,

000,

000 mb (

4800 tb)

每乙個資料塊需要的磁碟容量是:128 mb per block *1=

128 mb

集群可以容納的資料塊的數量:4

,800

,000

,000 mb /

128 mb =36,

000,

000 blocks

我們上面提到,一般情況下,一百萬的資料塊需要1g的記憶體,那麼36

,000

,000的資料塊就需要36gb的記憶體

集群b:200臺主機,每台主機的磁碟容量是24 tb,總共的磁碟容量大小是4800 tb

資料塊大小是128m,備份數是3

集群的磁碟容量:200*24

,000

,000 mb =4,

800,

000,

000 mb (

4800 tb)

每乙個資料塊需要的磁碟容量是:128 mb per block *3=

384 mb

集群可以容納的資料塊的數量:4

,800

,000

,000 mb /

384 mb =12,

000,

000 blocks

一般情況下,一百萬的資料塊需要1g的記憶體,那麼12

,000

,000的資料塊就需要12gb的記憶體

集群a和集群b的磁碟儲存容量都是一樣的,但是集群b因為備份數的增加,使得可以儲存的資料塊的數量變少了,所以集群b的namenode需要的記憶體相應的也變小了。

記生產上的一次事故

問題描述 生產環境上,使用者在登入登出時跳轉到了空白頁面,觀察位址列發現由原本的https變成了http,但是在測試環境上sit uat都是正常的。生產環境的部署大致是這樣子 ssl nginx f5 應用,在訪問ssl的時候請求是https,到了nginx請求就已經變成了http,proxy re...

Oracle 生產上表的列型別更新

由於粗心,資料庫指令碼生成的時候錯將乙個型別number 5 的字段型別改為 varchar2 5 直接進行表修改會報錯,因為資料已經存在,不能進行更新 alter table 表名 modify 表名.列名 number 5 大體思路如下 將要更改型別的欄位名改名以備份,然後新增乙個與要更改型別的...

記一次SQL語句的問題導致的生產上出現大問題的經歷

由於sql語句寫錯的問題,導致生產上出現問題。如下 public listfindbya string a return list 由於這裡是用jpa來實現sql語句的,而我在呼叫這個方法時候,傳進去之前,a沒有進行null判斷,導致a有可能會傳乙個null進去,從而導致引擎放棄使用索引而進行全表掃...