MongoDB是一個高性能可擴展基於文檔的NoSQL數據庫,高性能也需要在多個關鍵維度的配置,包括硬件、應用模式、模式設計、索引、磁盤I/O等。
存儲引擎
WiredTiger是3.0以后的默認存儲引擎,細粒度的並發控制和數據壓縮提供了更高的性能和存儲效率。3.0以前默認的MMAPv1也提高了性能。在MongoDB復制集中可以組合多鍾存儲引擎,各個實例實現不同的應用需求。
硬件
MongoDB初衷是采用水平擴展構建集群,而不是價格更高的硬件升級。采用復制保證高可用,自動分片使數據均勻分布在各節點服務器上;in-memory計算提供更高的計算性能,該引擎只有企業版有
硬件配置要求
- 確保內存設置能滿足性能需求:確保內存>索引容量+高頻訪問數據容量,通過storage.wiredTiger.engineConfig.cacheSizeGB或--wiredTigerCacheSizeGB進行設置。通過監控db.serverStatus()命令查看並評估
- 寫操作負載高的應用采用SSD:SATA接口的SSD提供強大的順序寫性能,能提高MongoDB數據和jounal日志文件的寫入速度;同時最為強大的是隨機讀取性能,這點符合MongoDB的數據訪問vi 模式。部署采用RAID-10,比RAID-5/RAID-6減少很多限制,並提供更高性能。
- 存儲引擎配置數據壓縮和I/O-intensive worloads:WiredTiger存儲引擎支持本地壓縮,能夠更好的使用多核新處理器資源。
- 為每個MongoDB服務提供專用服務器:在單一服務器上安裝多個MongoDB實例,系統會計算每個實例合適的緩存,並為每個實例分配默認的cache_size。通過storage.wiredTiger.engineConfig.cacheSizeGB參數調整。
- 使用多路查詢路由:在不同服務器上使用多個mongos,最好將mongos部署在應用服務器上。
- 利用多核心:WiredTiger存儲引擎是多線程且可以充分利用CPU多核心。MMAPv1存儲引擎因為其並發模型,所以並不要求更多的CPU核心。
- 開啟NTP時間同步服務
- 禁用NUMA:MongoDB運行在NUMA系統上會導致操作問題,禁用NUMA需要配置mermory interleave policy
編寫腳本/etc/init.d/pro-startMongo
...
# disable NUMA
sysctl -w vm.zone_reclaim_mode=0
啟動時必須指定numactl方式
numactl --interleave=all <path> <options>
- 禁用THP:Transparent Huge Pages(THP)是Linux內存管理策略會占用大量的內存
編寫腳本/etc/init.d/pro-startMongoDB,加入了前面禁用NUMA部分
# disable transparent hugespages case $1 in start) if [ -d /sys/kernel/mm/transparent_hugepage ]; then thp_path=/sys/kernel/mm/transparent_hugepage elif [ -d /sys/kernel/mm/redhat_transparent_hugepage ]; then thp_path=/sys/kernel/mm/redhat_transparent_hugepage else return 0 fi echo 'never' > ${thp_path}/enabled echo 'never' > ${thp_path}/defrag re='^[0-1]+$' if [[ $(cat ${thp_path}/khugepaged/defrag) =~ $re ]] then # RHEL 7 echo 0 > ${thp_path}/khugepaged/defrag else # RHEL 6 echo 'no' > ${thp_path}/khugepaged/defrag fi unset re unset thp_path # disable NUMA sysctl -w vm.zone_reclaim_mode=0 ;; esac
更改腳本權限並加入自啟動
sudo chmod 755 /etc/init.d/pro-startMongo
sudo chkconfig --add pro-startMongo
通過以下測試是否關閉了THP
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag
如下顯示表示成功
always madvise [never]
- 設置ulimit:默認的ulimit設置太小,以下是推薦設置
-f (file size): unlimited
-t (cpu time): unlimited
-v (virtual memory): unlimited
-n (open files): 64000
-m (memory size): unlimited
-u (processes/threads): 64000
我是新建/etc/security/limits.d/99-mongodb-nproc.conf文件,加入如下配置:
mongod soft fsize unlimited
mongod hard fsize unlimited
mongod soft cpu unlimited
mongod hard cpu unlimited
mongod soft as unlimited
mongod hard as unlimited
mongod soft nofile 64000
mongod hard nofile 64000
mongod soft nproc 64000
mongod hard nproc 64000
應用、模式設計
- 模式設計:關聯模式和嵌套模式,見下圖,根據應用設計最合理的模式。
- 文檔的key命名盡量短,比如ParkingId可以改為pid。超過16MB,大文檔盡量使用GridFS
- 在集群環境下,避免scatter-gather查詢。其實這依賴於sharding的方式和sharding key的選擇,要盡量滿足大部分的業務需求。
- 讀寫分離設計:在讀延遲允許范圍內,進行讀寫分離是個不錯的選擇,可以大大降低主節點壓力。
- 類似關系型數據庫,一些優化建議:只查詢和更新需要的字段,減少帶寬;避免使用否定條件查詢;合理使用覆蓋索引並考慮最左前綴匹配原則;
硬盤I/O
- 預讀設置:使用blockdev --setra <value>命令設置預讀,單位是512B(扇區大小),不少於32kb,也不要設置太大,浪費I/O,設置大的預讀有助於順序讀,具體的配置根據業務需求設定。
- 使用EXT4或者XFS文件系統。不要使用EXT3哦。
- 禁止Access Time設置。操作系統會維護文件最后的訪問時間metadata,對於數據庫意味着每次文件系統每訪問一個頁就會提交一個寫操作,這將降低整個數據庫的性能。
編輯/etc/fstab文件,指定noatime和nodiratime
/dev/sdb /data ext4 defaults,noatime,nodiratime 1 2
- 禁用Huges Pages虛擬內存頁,MongoDB使用普通虛擬內存頁性能更好,這個前面提到過。
- 使用RAID10,性能高於RAID-5或RAID-6
- swap設置:設置充足的swap空間防止OOM程序殺掉mongod進程,對於Linux下的MMAPv1存儲引擎,不會使用swap空間,可以少量設置swap空間;Windows下的MMAPv1存儲引擎需要設置swap空間;WiredTiger存儲引擎,需要設置較大的swap空間。使用WiredTiger測試過程中,發現對於大查詢,沒有足夠的swap空間甚至會報錯。在/etc/sysctl.conf設置vm.swappiness為0,盡量使用內存。swap分區盡可能大些,以下是一些建議。測試過程中是128G內存,我設置交換分區內存大小也是128G。

- 日志和數據文件分開存儲,日志存儲在普通SAS盤上,數據存儲在SSD上。數據庫的讀一般都是隨機讀,SSD在隨機讀性能上表現非常好;日志文件主要是順序寫,速度本身較高,而SSD在順序讀寫上的表現非常糟糕,而且比普通SATA性能還要低。Mongodb的日志有journal和syslog,journal日志只能放在dbPath下面的journal目錄中,而系統日志可以指定日志路徑。journal可以掛載個SATA硬盤設備。這樣做到日志和數據分離。
- 多路徑設置:設置storage.wiredTiger.engineConfig.directoryForIndexes使索引和數據分離,設置該參數為true后,會在dbPath下面建立一個index目錄,在index目錄下掛載一個硬盤設備,使索引和數據做到分離。設置directoryPerDB每個數據庫不同目錄,對於每個目錄最好掛載到不同的硬盤設備上。
- 壓縮:WiredTiger提供snappy和zlib兩種數據壓縮方式。snappy提供壓縮比低但是性能損耗低,zlib壓縮比高但性能損耗較高,通過storage.wiredTiger.collectionConfig.blockCompressor參數設置