在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進去,從而導致引擎放棄使用索引而進行全表掃...