MongoDB服務器在默認安裝下不啓用鑑權。這意味着每一個人均可以直接鏈接到mongod實例並執行任意數據庫操做。html
MongoDB支持按角色定義的權限系統。你應該基於「最少權限」準則,顯式的爲用戶分配僅須要的相應權限。mongodb
儘量使用LDAP、Kerbero之類的中央鑑權服務器,並使用強口令策略。數據庫
若是你的服務器有多個網卡,建議只在內網的IP上監聽服務。緩存
MongoDB企業版支持存儲加密,對涉及到客戶的敏感數據應該使用加密引擎來保護數據。安全
MongoDB的建議最小部署是3個數據節點構成的複製集。複製集能夠提供如下優勢:服務器
分片能夠用來擴展你係統的讀寫能力,可是分片也會帶來很多新的挑戰好比說管理上的複雜度,成本的增長,選擇合適片鍵的挑戰性等等。通常來講,你應該先窮盡了其餘的性能調優的選項之後纔開始考慮分片,好比說,索引優化,模式優化,代碼優化,硬件資源優化,IO優化等。網絡
分片的一些觸發條件爲:併發
分片之間的數據互相不復制。每一個分片的數據必須在分片內保證高可用。所以,對每個分片MongoDB要求至少部署3個數據節點來保證該分片在絕大部分時間都不會由於主節點宕機而形成數據不可用。異步
在分片場景下, 最重要的一個考量是選擇合適的片鍵。選擇片鍵須要考慮到應用的讀寫模式。一般來講一個片鍵要麼是對寫操做優化,要麼是對讀操做優化。要根據哪一種操做更加頻繁而進行相應的權衡。分佈式
MongoDB是一個高性能高併發的數據庫,其大部分的IO操做爲隨機更新。通常來講本機自帶的SSD是最佳的存儲方案。若是使用普通的硬盤,建議使用RAID10條帶化來提升IO通道的併發能力。
MongoDB不少的性能瓶頸和IO相關。建議爲日誌盤(Journal和系統日誌)單獨設定一個物理卷,減小對數據盤IO的資源佔用。 系統日誌能夠直接在命令行或者配置文件參數內指定。Journal日誌不支持直接指定到另外的目錄,能夠經過對Journal目錄建立symbol link的方式來解決。
MongoDB在WiredTiger存儲引擎下建議使用XFS文件系統。Ext4最爲常見,可是因爲ext文件系統的內部journal和WiredTiger有所衝突,因此在IO壓力較大狀況下表現不佳。
WiredTiger 對寫操做的落盤是異步發生的。默認是60秒作一次checkpoint。作checkpoint須要對內存內全部髒數據遍歷以便整理而後把這些數據寫入硬盤。若是緩存超大(如大於128G),那麼這個checkpoint時間就須要較長時間。在checkpoint期間數據寫入性能會受到影響。目前建議實際緩存設置在64GB或如下。
Transparent Huge Pages (THP) 是Linux的一種內存管理優化手段,經過使用更大的內存頁來減小Translation Lookaside Buffer(TLB)的額外開銷。 MongoDB數據庫大部分是比較分散的小量數據讀寫,THP對MongoDB這種工況會有負面的影響因此建議關閉。 http://docs.mongoing.com/manual-zh/tutorial/transparent-huge-pages.html
防止MongoDB 的log文件無限增大,佔用太多磁盤空間。好的實踐是啓用log rotation並及時清理歷史日誌文件。
足夠的Oplog空間能夠保證有足夠的時間讓你從頭恢復一個從節點,或者對從節點執行一些比較耗時的維護操做。假設你最長的下線維護操做須要H小時,那麼你的Oplog 通常至少要保證能夠保存 H 2 或者 H3 小時的oplog。
禁止系統對文件的訪問時間更新會有效提升文件讀取的性能。這個能夠經過在 /etc/fstab 文件中增長 noatime 參數來實現。例如: /dev/xvdb /data ext4 noatime 0 0
修改完文件後從新 mount就能夠: mount -o remount /data
Linux默認的文件描述符數和最大進程數對於MongoDB來講通常會過低。建議把這個數值設爲64000。由於MongoDB服務器對每個數據庫文件以及每個客戶端鏈接都須要用到一個文件描述符。若是這個數字過小的話在大規模併發操做狀況下可能會出錯或沒法響應。 你能夠經過如下命令來修改這些值: ulimit -n 64000 ulimit -u 64000
在一個使用NUMA技術的多處理器Linux 系統上,你應該禁止NUMA的使用。MongoDB在NUMA環境下運行性能有時候會可能變慢,特別是在進程負載很高的狀況下。
預讀值是文件操做系統的一個優化手段,大體就是在程序請求讀取一個頁面的時候,文件系統會同時讀取下面的幾個頁面並返回。這緣由是由於不少時候IO最費時的磁盤尋道。經過預讀,系統能夠提早把緊接着的數據同時返回。假設程序是在作一個連續讀的操做,那麼這樣能夠節省不少磁盤尋道時間。 MongoDB不少時候會作隨機訪問。對於隨機訪問,這個預讀值應該設置的較小爲好.通常來講32是一個不錯的選擇。你可使用下述命令來顯示當前系統的預讀值: blockdev --report
要更改預讀值,能夠用如下命令: blockdev --setra 32
在使用MongoDB複製集或者分片集羣的時候,注意必定要使用NTP時間服務器。這樣能夠保證MongoDB集羣成原則之間正確同步。
這個是針對於數據量較大好比說超過幾十上百萬(文檔數目)數量級的集合。若是沒有索引MongoDB須要把全部的Document從盤上讀到內存,這會對MongoDB服務器形成較大的壓力並影響到其餘請求的執行。
若是你的查詢會使用到多個字段,MongoDB有兩個索引技術可使用:交叉索引和組合索引。交叉索引就是針對每一個字段單獨創建一個單字段索引,而後在查詢執行時候使用相應的單字段索引進行索引交叉而獲得查詢結果。交叉索引目前觸發率較低,因此若是你有一個多字段查詢的時候,建議使用組合索引可以保證索引正常的使用。 例如,若是應用須要查找全部年齡小於30歲的運動員: db.athelets.find({sport: "marathon", location: "sz", age: {$lt: 30}}})
那麼你可能須要這樣的一個索引: db.athelets.ensureIndex({sport:1, location:1, age:1});
以上文爲例子,在建立組合索引時若是條件有匹配和範圍之分,那麼匹配條件(sport: 「marathon」) 應該在組合索引的前面。範圍條件(age: ❤️0)字段應該放在組合索引的後面。
有些時候你的查詢只須要返回不多甚至只是一個字段,例如,但願查找全部虹橋機場出發的全部航班的目的地。已有的索引是: {origin: 1, dest: 1}
若是正常的查詢會是這樣(只須要返回目的地機場): db.flights.find({origin:"hongqiao"}, {dest:1});
這樣的查詢默認會包含_id 字段,因此須要掃描匹配的文檔並取回結果。相反,若是使用這個查詢語句: db.flights.find({origin:"hongqiao"}, {_id:0, dest:1});
MongoDB則能夠直接從索引中取得全部須要返回的值,而無需掃描實際文檔(文檔可能須要從硬盤裏調入到內存)
在對一個集合建立索引時,該集合所在的數據庫將不接受其餘讀寫操做。對數據量的集合建索引,建議使用後臺運行選項
Java驅動的默認鏈接池大小是100。建議按照應用的實際狀況作調整。對壓力較小的應用能夠適當調小減小對應用服務器的資源佔用。
MongoDB的建議最小部署是一個複製集,包含3個數據節點。默認狀況下應用的寫操做(更新,插入或者刪除)在主節點上完成後就會當即返回。寫操做則經過OPLOG方式在後臺異步方式複製到其餘節點。在極端狀況下,這些寫操做可能還未在複製到從節點的時候主節點就出現宕機。這個時候發生主備節點切換,原主節點的寫操做會被回滾到文件而對應用不可見。爲防止這種狀況出現,MongoDB建議對重要的數據使用 {w: 「marjority」} 的選項。{w: 「majority」} 能夠保證數據在複製到多數節點後才返回成功結果。使用該機制能夠有效防止數據回滾的發生。 另外你可使用 (能夠和 w:」majrotiy」 結合使用) 來指定數據必須在寫入WAL日誌以後才嚮應用返回成功確認。這個會致使寫入性能有所降低,可是對於重要的數據能夠考慮使用。
MongoDB因爲是一個分佈式系統,一份數據會在多個節點上進行復制。從哪一個節點上讀數據,要根據應用讀數據的需求而定。如下是集中能夠配置的讀選項:
MongoClient是個線程安全的類,自帶線程池。一般在一個JVM內不要實例化多個MongoClient實例,避免鏈接數過多和資源的沒必要要浪費。
MongoDB使用複製集技術能夠實現99.999%的高可用。當一臺主節點不能寫入時,系統會自動故障轉移到另外一臺節點。轉移可能會耗時幾秒鐘,在這期間應用應該捕獲相應的Exception並執行重試操做。重試應該有backoff機制,例如,分別在1s,2s,4s,8s等時候進行重試。
MongoDB 沒有表結構定義。每一個文檔的結構由每一個文檔內部的字段決定。全部字段名會在每一個文檔內重複。使用太長的字段名字會致使對內存、網絡帶寬更多的需求。(因爲壓縮技術,長字段名對硬盤上的存儲不會有太多佔用)
MongoDB 支持相似於SQL語句裏面的select,能夠對返回的字段進行過濾。使用Projection能夠減小返回的內容,下降網絡傳輸的量和代碼中轉化成對象所需的時間。
不少時候咱們用MongoDB來存儲一些時效性的數據,如7天的監控數據。與其本身寫個後臺腳本按期清理過時數據,你可使用TTL索引來讓MongoDB自動刪除過時數據: db.data.ensureIndex({create_time:1}, {expireAfterSeconds: 7*24*3600})