MongoDB 限制 儲存空間

MongoDB的儲存限制

夏宏彰 2016/07/25 09:49:18
5485







主題

MongoDB儲存限制

文章簡介

說明MongoDB儲存限制超過MongoDB儲存限制的處理方式

作者

夏宏彰

版本/產出日期

V1.0/2016.7.14




1. 前言

2. 目的

3. 開始前準備

4. MongoDB Memory 使用方式

5. MongoDB Memory Limit – 32TB

6. 超過 32TB 會發生什麼事 ?

7. 問題解決

8. 參考 :





1. 前言

本文件用來提供MongoDB或WingDB的操作人員如何處理當MongoDB超過儲存容量限制時發生的狀況。

使用MongoDB 2.6.6 Linux (64bit)進行說明。


其他相關名詞:

Replica Set: MongoDB的複製集,可以達到資料的非同步抄寫與錯誤回復的需求。

Shard Cluster: 分割叢集,可以將大量的資料分割到多個MongoDB,達到橫向擴充的目的。


2. 目的

了解MongoDB的儲存限制。

處理MongoDB Out Of Memory的狀況。


3. 開始前準備

本說明基於以下版本的環境:

MongoDB 2.6.6 (64bit)

RedHat 7


提供對象:

MongoDB資料初步的了

MongoDB Replica Set運作

MongoDB Shard Cluster運作


4. MongoDB Memory使用方式

遇到MongoDB了大量的Memory至將系統的Memory光了,所以他想要限制MongoDB使Memory大小實際上是無法限制的也不要想用其他方法,這與MongoDB存檔案用的式有關,且但限制,他限的就是你的資料量


MongoDBMemory-Mapped Files的格放資料,Memory-Mapped File 是作業系統透過mmap()存放memory資料用的檔案。也就是說mmap()將檔案對映到virtual memory的一個區域,資由記憶載入移出Linux管理的而是否行快取、快取的大小何,同Linux決定我們Linux透過topmongodprocessesMongoDB用的體記憶體(RES)部分並不大,但它所使用的虛擬記憶體(VIRT)就相驚人就是MongoDBVirtual Memory錄資料的說明以我們可以也不能限制MongoDB使用記體的大其是virtual memory定成unlimited,若你的料量很大的話限制virtual memory是限制你存放的資料量


MongoDB會用到LinuxSwap? data不會由上述說明可data部分本身就是virtual memory,但其他如連線的部分還是有可能用到。ClientMongoDB的連線每一條約用1MB記憶體,基本上是不太能用到1GB上的記憶體,但為了避Linuxoom-killer或是統上時也有其他應用執行,建議設定以維統的穩定


圖是top例子,以第一mongod言虛擬記憶體45.44TB體記憶體用量僅有約30GB

>top


圖是同mongodmongostat例子,們看到vsize46530gtop看到45.44T一致的res1.76g,這top當的落差應該是算的方式不同吧! 看到mapped此即所Memory-Mapped大小,是實MongoDB存資料大小vsizemapped的兩倍大。

> mongostat


5. MongoDB Memory Limit – 32TB

什麼? MongoDB 64bit有儲存資料大小的限制!


是的,MongoDB使用Virtual Memory記錄資料,所以底層OS的virtual memory address space的極限就是MongoDB所能記錄資料大小的極限。但64bit很大吧,是Long資料的最大值吔! 應該很難超過才是。但實際上64bit作業系統的空間限制並非2^64 (1.8EB)這麼大,以RedHat而言,不同版本的64bit也不同,如下表所示:


(參考: https://access.redhat.com/articles/rhel-limits)


但MongoDB的資料大小限制是128TB嗎? 再來看下表:


(參考: https://docs.mongodb.com/v2.6/reference/limits/#data)


沒錯,virtual memory的限制當Not Journaled是128TB,但若有使用Journal則只剩一半64TB,而memory mapped的大小是virtual memory的一半,所以就僅有32TB可用。換算成MongoDB的data files數量約為16000個,一個2GB計算下來也剛好是32TB。



6. 32TB什麼事?

32TB的確沒有那麼容易超過,就算要超過一般也是好幾個月以後的事,也可能是好幾年後。我們要先預估系統資料可能的成長,可一開始就規劃成Shard Cluster,或是等資料確實達到某一個值時再來擴充。


以MongoDB能夠將現行standalone轉換成shard的限制來看,若一開始就預估資料會成長200G以上時,建議一開始就規劃成Shard Cluster,否則就不用,畢竟Shard Cluster的建制成本與複雜度比Replica Set多了好幾倍。


再回來看,單台MnogoDB用超過32TB時資料將無法再寫入,Java Client出現的錯誤大概如下:

"code" : 12520 - "new file allocation failure"

"code" : 14031 - "Can't take a write lock while out of disk space"


com.mongodb.WriteConcernException: { "serverUsed" : "localhost" , "ok" : 1 , "n" : 0 , "err" : "new file allocation failure" , "code" : 12520}

    at com.mongodb.CommandResult.getWriteException(CommandResult.java:90)

    at com.mongodb.CommandResult.getException(CommandResult.java:79)

    at com.mongodb.DBCollectionImpl.translateBulkWriteException(DBCollectionImpl.java:316)


com.mongodb.WriteConcernException: { "serverUsed" : "localhost:28001" , "ok" : 1 , "n" : 0 , "err" : "Can't take a write lock while out of disk space" , "code" : 14031}

    at com.mongodb.CommandResult.getWriteException(CommandResult.java:90)

    at com.mongodb.CommandResult.getException(CommandResult.java:79)

    at com.mongodb.DBCollectionImpl.translateBulkWriteException(DBCollectionImpl.java:316)



MongoDB Server端出現的錯誤如下:

errno:12 Can not allocate memory

ERROR: mmap failed with out of memory. (64 bit build)

Assertion: mmf.opne failed

13636 open/create failed in createPrivateMap //show dbs


2016-06-15T13:13:16.974+0800 [conn13432] ERROR: mmap() failed for /data/MYDB.5019 len:2146435072 errno:12 Can not allocate memory

2016-06-15T13:13:16.974+0800 [conn13432] ERROR: mmap failed with out of memory. (64 bit build)



出錯的Database(一MongoDB可建立多個Database)亦無法讀取資料,但其他非出錯的Database仍可讀取資料(findOne())。查詢時出現錯誤如下:

13636 ”open/create failed in createPrivateMap


7. 問題解決

另建DB儲存過多的資料; 若原本是Shard Cluster,則新增Shard以擴充資料空間。已出錯的Database只能刪除,看來是無法將資料復原了。為了預防此問題再度發生,可另外設一監控機制,例如當Memory Mapped超過20TB,或是Virtual Memory超過40TB時則要準備新增一個Shard,適當的設定Shard Key。


    刪除Sharded Database (ex. MYDB)要注意的問題:

刪除要先將Balancer停止

sh.stopBalancer();

否則Balancer做到一半的問題會在重建相同DB Name後出現moveChunk fail問題。

刪除失敗,顯示Device busy

這可能是各Database單獨mount進來的volume無法真正刪除所造成的錯誤訊息,一般可以乎略。

可直接到各個instancedataPath將該目錄清空(MYDB>rm -fr *)

若是用link方式建立目錄,則需重新連結:

localhost>ln -s /storage/MYDB ./MYDB

刪除正常,但show dbs仍存在該DB name,或是顯示(empty)

這大部分是因為各shardDatabase沒有真正刪除乾淨,可由各shardPrimary進入再刪除,或是直接到各個instancedataPath將該目錄清空(MYDB>rm -fr *)

configServer上舊DB的配置資料手動刪除乾淨

mongos>use config

mongos>db.chunks.remove({“ns”:/^MYDB.*/});

mongos>db.collections.remove({“_id”:/^MYDB.*/});

mongos>db.tags.remove({“ns”:/^MYDB.*/});

重啟Balancer

sh.startBalancer();

可重敗的MYDB!

先準備好一組Replica Set

Shard Cluster

若有Shard TagsTags新的Shard


重建Sharded Database (ex. MYDB)要注意的問題:

moveChunk fail

由於刪除MYDB時未先將Balancer停止,造成原作業一直在等待lock,無法將新建的Sharded DatabaseShard Collectionchunks依我們指定的tags正確的移到相對應的shard

解決方式:

例如chunks無法移到Shard001,則表示Shard001有等待lock的狀況,可將Shard001Primary setpDown(),則在該Primary等待lock的作業會立即停止。

mongoslog確認moveChunk問題不再發生。

3 ~ 5min後,sh.status()查看chunks已移到Shard001上。

完成。


8. 參考:

What are memory mapped files?

https://docs.mongodb.com/v2.6/faq/storage/#what-are-memory-mapped-files


Do I need to configure swap space?

https://docs.mongodb.com/v2.6/faq/diagnostics/#memory-diagnostics


How do I calculate how much RAM I need for my application?

https://docs.mongodb.com/v2.6/faq/diagnostics/#how-do-i-calculate-how-much-ram-i-need-for-my-application


Red Hat Enterprise Linux technology capabilities and limits

https://access.redhat.com/articles/rhel-limits


MongoDB Limits and Thresholds - Data

https://docs.mongodb.com/v2.6/reference/limits/#data


MongoDb DropDatabase Not Working

http://stackoverflow.com/questions/9407838/mongodb-dropdatabase-not-working


moveChunk failed to engage TO-shard in the data transfer

http://stackoverflow.com/questions/26640861/movechunk-failed-to-engage-to-shard-in-the-data-transfer-cant-accept-new-chunk


夏宏彰