有些情況會使得mongo nodes全安裝在同台機器中(用不同port來達成),
但卻會讓所有的mongo nodes之間互相搶資源導致被OOM killer給幹掉,
因此正式運營絕對是一台device一個node是最安全/穩定的
不過最近無意中發現OOM killer挑的對象並非我所想像,
以下列出兩種mongo資源互搶所導致的狀況。
1. CPU鎖死性消耗
#記憶體資源分配問題:
mongo daemon為了運作穩定,
因此常常預先blocked記憶體區塊,
但mongod在爭取資源時為貪婪式的 (根據一些狀況猜測),
所以當資源消耗完,但OOM killer 卻無動於衷時,
mongod是無法得知也沒有偵測方法(高度OS管理依賴),
如果OS資源不夠,mongod無法要到資源時,
此時mongod通常會作罷,
會去清掉自己記憶體原有的使用或是轉為硬碟存取為主,
會去清掉自己記憶體原有的使用或是轉為硬碟存取為主,
然而mongod在處理同步(或其他高記憶體需求)時,
被OS記憶體管理拒絕後,這些需求仍在不會消失,
最後會導致Sync Process不斷的被開啟後關閉行為,
也就會讓我們在CPU上看到幾乎100%消耗,
而IO或Networks低使用的狀況
#同樣會發生CPU鎖死性消耗也跟設定有關:
(注意,即使在不同實體上也會發生!)
如果設定一組replication set時切割記憶體空間請注意是否相同
包括secondary再內的所有結點,
記憶體空間若大於primary則沒事,
但若小於primary所配置的空間時,
同步機制會參考記憶體配置而不斷強迫開啟process去處理這件事,
但同樣的遇到OOM killer因空間不夠而強迫終止,
由於需求不會突然消失,
所以CPU資源會繼續消耗下去直到重開或是記憶體夠用為止。
而IO或Networks低使用的狀況
#同樣會發生CPU鎖死性消耗也跟設定有關:
(注意,即使在不同實體上也會發生!)
如果設定一組replication set時切割記憶體空間請注意是否相同
包括secondary再內的所有結點,
記憶體空間若大於primary則沒事,
但若小於primary所配置的空間時,
同步機制會參考記憶體配置而不斷強迫開啟process去處理這件事,
但同樣的遇到OOM killer因空間不夠而強迫終止,
由於需求不會突然消失,
所以CPU資源會繼續消耗下去直到重開或是記憶體夠用為止。
2. Who is OOM killer target ?
http://unix.stackexchange.com/questions/153585/how-oom-killer-decides-which-process-to-kill-first
根據這篇文章來看,
OOM killer會砍掉"最不重要" 中 "記憶體佔比高"的程序,如果都沒得選就選pid高的
但OS不是很在乎 mongo nodes之間的資源爭奪,
所以出現上面描述的(CPU bound)資源飢餓時是沒有反應的,
不過大量擁入連線時會向OS請求開啟新連線,
此時buffer或其他相關性系統資源會開始大量消耗,
如此一來在OS中的所有mongo nodes就會成為目標,
後來發現OOM砍掉的daemon並非我原本預估的。(如圖)
圖中有兩個崖,第一個是OOM幹的,第二個是手動
如此可以明白一件事,對OOM最值得砍的絕對不是最大佔比優先
觀察程序發現不但是最少而且多半有點閒置狀況,
讓我猜想會不會是只要OS夠用就行,
竟量砍小的在一般假設上會比較不會影響到一般程序使用,
對OS來說大概是用記憶體多代表愈重要。
結論:
Production MongoDB Cluster 所有Nodes都要獨立機器。
(如果只是要測試目前只能建議跟我一樣安裝自動重啟和手動砍掉高佔記憶體的Process)
補充1:
找到一方法可以減少mongoDB搶資源的問題,
查mongo設定後cache預設會吃60%資源,
因此如果要避免同台機器上面資源搶太兇,
使用wiredTiger engine可以考慮使用 wiredTigerCacheSizeGB 參數去限制使用量
效果挺好低~
補充2:
在個別獨立機器上也有發生過類似的事情,
就是在大量的update後(非常大,幾乎將primary頂到不能呼吸了
隨即刪除所有update過的資料,
這時候secondary node需要拉原始資料去更新(因為更新只有journal可以參考),
再加上所有指令是要排順序的,
所以secondary node並不知道資料已經在primary中已被刪除,
最後導致sec. node不斷的去掃資料,看能不能找到需要更新的record
如果這情況不多還好,但這狀況是可以被累積的,
一旦數量增加,就會讓sec.可用thread不斷減少。
基本上對於cluster影響層次不大,影響最多的是從sec. node去拉資料的client
以及同步資料的正確性,因為很多threads被卡住,
最後也可能導致sec. node完全失去作用。
補充3:
for 補充2的問題,經過多次反覆測試,確認是記憶體因為資料量太大,
再加上多核心計算的硬體設定,會導致CPUs之間和記憶體通道之間堵塞
最後才導致同步速度太慢,可以用numa平均且分散在各記憶體通道中
減輕全部塞在同個通道問題,事後反覆壓力測試下證實有用。
補充4:
有時因為master或slave過度busy
如果干擾時間太舊會導致同步減慢或失常
這時系統的oplog size太小
就會導致無法同步,slave node會永遠閒置在那裡
即使清掉重新同步也有可能無法追上
因為資料量大的話,從新同步時間 > oplog可以承受的時間時
只有把node停掉才有用 (但上線的service無法關閉
所以可以考慮一開始就把oplog size放大
官方預設值為5% (但檢查時好像不是每次都會到5%??
若寫入資料量夠大時,可以考慮到10%
沒有留言:
張貼留言