1. 性能優化分類
mongodb性能優化分為軟件層面和操作系統層面。
軟件層面,一般通過修改mongodb軟件配置參數來達到,這個需要非常熟悉mongodb里面的各種配置參數;
而操作系統層面,相對簡單點,主要是修改操作系統參數,比如說:關閉傳輸頁緩存、使用SSD替代機器硬盤等等。
2. 軟件層面優化
2.1 設置WiredTiger的cacheSizeGB
通過cacheSizeGB選項配置控制WiredTiger引擎使用內存的上限,默認配置在系統可用內存的60%左右。
如果一台機器上只部署一個mongod,mongod可以使用所有可用內存,則使用默認配置即可。
如果一台機器上部署多個mongod,或者mongod跟其他的一些進程一起部署,則需要根據分給mongod的內存配額來配置cacheSizeGB,按配額的60%左右配置即可。
通過配置文件配置cacheSizeGB,如下:
2.2 分配足夠的Oplog空間
Oplog是MongoDB local庫下的一個固定集合,Secondary就是通過查看Primary 的oplog這個集合來進行復制的。Oplog可以說是MongoDB Replication的紐帶。Oplog是固定大小的,它只能保存特定數量的操作日志。如果oplog size過大,會浪費存儲空間;如果oplog size過小,老的oplog記錄很快就會被覆蓋,那么宕機的節點很容易出現無法同步數據的現象,因此設置合理的oplog大小對mongodb很重要。MongoDB默認將其大小設置為可用disk空間的5%(默認最小為1G,最大為50G)。
這里設置oplog為10000MB,如:
2.3 啟用Log Rotation日志切換
防止MongoDB的log文件無限增大,占用太多磁盤空間。使用Log Rotation並及時清理歷史日志文件,在配置文件配置如下紅框設置。
logRotate:日志回轉,防止一個日志文件特別大,可選值:rename,重命名日志文件,默認值;reopen,使用Linux日志rotate特性,關閉並重新打開次日志文件,可以避免日志丟失,但是logAppend必須為true。
timeStampFormat:指定日志格式的時間戳格式,可選值:ctime,顯示時間戳Wed Dec 31 18:17:54.811;Iso8601-utc,顯示時間戳以協調通用時間(UTC)在ISO-8601中的格式,例如,紐約時代的開始時間:1970-01-01t00:00: 00.000z;iso8601-local,顯示當地時間ISO-8601格式顯示時間戳
2.4 設置journal日志刷新時間和flush時間
commitIntervalMs:mongod的journal日志刷新值范圍從1到500毫秒。較低的值增加了journal的耐久性,以犧牲性能為代價,在WiredTiger引擎上,默認的日志提交間隔為100毫秒,增大commitIntervalMs可以降低磁盤的IO壓力,起到一定的優化作用。不過一般情況下,不建議修改。
syncPeriodSecs:mongod使用fsync操作將數據flush到磁盤的時間間隔,默認值為60(單位:秒),增大該值也可以降低磁盤IO壓力,起到一定優化作用。一般情況下,強烈建議不要修改此值。mongod將變更的數據寫入journal后再寫入內存,並間歇性的將內存數據flush到磁盤中,即延遲寫入磁盤,有效提升磁盤效率。此指令不影響journal存儲,僅對mongod有效。
3. 系統層面優化
3.1 MongoDB連接內存優化
MongoDB服務器內存要滿足connection overhead + data size + index size,即連接數開銷 + 熱點數據 + 索引。
linux操作系統默認每個連接數占用10M內存。
使用ulimit -a 查看stack size,即為每個連接數占用的內存。
所有連接數消耗的內存加起來相當驚人,推薦把Stack設置小一點,比如說1024:在linux命令窗口輸入ulimit -s 1024。這種方式的缺點是,重新打開一個shell命令窗口就失效啦,需要重新執行這一條命令。
永久生效的方式,修改/etc/profile,在最后添加ulimit -s 1024,然后保存並source /etc/profile
3.2 MongoDB連接數優化
MongoDB連接數主要是通過提高操作系統的默認文件描述符和進程/線程數限制。Linux默認的文件描述符數和最大進程數對於MongoDB來說一般會太低。建議把這個數值設為100000以上。因為MongoDB服務器對每一個數據庫文件以及每一個客戶端連接都需要用到一個文件描述符。如果這個數字太小的話在大規模並發操作情況下可能會出錯或無法響應。報以下錯誤信息:
"too many open files" "too many open connections"
上面報錯的信息,說明打開的連接數太多了,有兩個限制mongod/mongos連接數的地方:
① 操作系統的ulimit限制,本節重點介紹;
② mongodb自身的限制;
操作系統的ulimit限制,可以用ulimit -a查看open files,是否夠大。linux下默認的open files是1024,在提供服務的時候往往太小。
可以通過以下命令來修改這些值,暫時性,重新打開shell命令窗口會失效:
ulimit -n 1048576 ulimit -u 524288
這時可以通過修改/etc/security/limits.conf( 部分的系統是在/etc/security/limits.d/90-nproc.conf)持久化設置允許用戶/進程打開文件句柄數,這一步需要重啟系統,不然不起作用,在limits.conf添加如下設置:
* soft nofile 1048576 * hard nofile 1048576 * soft nproc 524288 * hard nproc 524288
3.3 關閉Transparent Huge Pages
Transparent Huge Pages(THP)是Linux的一種內存管理優化手段,通過使用更大的內存頁來減少Translation Lookaside Buffer(TLB)的額外開銷。MongoDB數據庫大部分是比較分散的小量數據讀寫,THP對MongoDB這種情況會有負面的影響,所以建議關閉。
暫時性的做法,會失效:
echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag
永久性做法,修改/etc/rc.d/rc.local,添加如下設置:
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then echo never > /sys/kernel/mm/transparent_hugepage/enabled fi if test -f /sys/kernel/mm/transparent_hugepage/defrag; then echo never > /sys/kernel/mm/transparent_hugepage/defrag fi
3.4 使用XFS文件系統,同時禁掉數據庫文件的atime
MongoDB在WiredTiger存儲引擎下建議使用XFS文件系統。Ext4最為常見,但是由於ext文件系統的內部journal和WiredTiger有所沖突,所以在IO壓力較大情況下表現不佳。
在使用XFS文件系統的同時,我們建議在文件系統的mount參數上加上noatime,nodiratime兩個選項。用noatime mount的話,文件系統在程序訪問對應的文件或者文件夾時,不會更行對應的access time。
一般來說,Linux會給文件記錄三個時間,change time,modify time 和 access time。我們可以通過stat來查看文件的三個時間。其中access time指文件最后一次被讀取的時間,modify time指的是文件的文本內容最后發生變化的時間,change time指的是文件的inode最后發生變化(比如位置、用戶屬性、組屬性等)的時間。
一般來說,文件都是讀多寫少的,而且我們也很少關心某一文件最近什么時間被訪問了,所以,我們建議采用noatime選項,這樣文件系統不記錄access time,避免浪費資源。禁止系統對文件的訪問時間更新會有效提高文件讀取的性能。
操作如下:
1) Centos7的安裝xfsprogs-4.5.0-15.el7.x86_64.rpm包,而Centos6的安裝xfsprogs-3.1.1-20.el6.x86_64.rpm。
rpm -ivh xfsprogs-3.1.1-20.el6.x86_64.rpm
2) 格式化為XFS文件系統,有兩種情況,一是把已存在的Ext4等文件系統格式化為XFS文件系統,二是把尚未格式化的磁盤格式化為XFS文件系統。
一、把已存在的Ext4格式化為XFS文件系統,以/opt目錄為例,我們把/opt作為mongodb的安裝及存儲目錄:
① 首先使用命令 lsblk -f 查看磁盤分區及其對應的目錄
② 然后 umount /opt 把/opt目錄卸載掉
③ 使用 mkfs.xfs -f /dev/sda5 把ext4文件系統覆蓋為xfs文件系統,並使用lsblk -f查看是否修改成功
④ 接着修改/etc/fstab文件,讓系統開機自動掛載該磁盤分區為/opt,在/etc/fstab文件里,把/opt對應那行的ext4改為xfs,並在defaults后面加上“,noatime”,把atime禁掉
⑤ 最后,把/opt掛載上,並禁掉atime,並用 lsblk -f 查看
二、把尚未格式化的磁盤格式化為XFS文件系統
① 首先使用命令 fdisk -l 查看空閑的磁盤分區
從上圖可以看出磁盤/dev/sda總大小為42.9GB,/dev/mapper/centos-root占用29GB,而/dev/mapper/centos-swap占用2GB,故空余尚未格式化的磁盤大約占10GB;磁盤/dev/sda占用83886080個sectors,而目前/dev/sda2使用到的sectors為62914559,還剩余20971521個sectors尚未使用,這也是看出尚未格式化的磁盤的方法;
② 創建新的磁盤分區
③ 執行partprobe或者重啟
執行 partprobe 命令用於將磁盤分區表變化信息通知內核,並請求操作系統重新加載分區表,可以避免必須重新啟動的問題
執行 partprobe 命令之前,使用 lsblk -f 來查看磁盤分區,沒有看到/dev/sda3;執行 partprobe 命令后,再次使用 lsblk -f 查看磁盤分區
后面的操作同方式一的④⑤操作,掛載並禁掉atime,最后在/etc/fstab上面添加/dev/sda3及其對應掛載的路徑
3.5 使用SSD或RAID10來提供存儲IOPS能力
MongoDB是一個高性能高並發的數據庫,其大部分的IO操作為隨機更新。一般來說本機自帶的SSD是最佳的存儲方案。如果使用普通的磁盤,建議使用RAID10條帶化來提供IO通道的並發能力。
注意:
IOPS (Input/Ouput Operations Per Second):是存儲設備每秒讀寫的次數。
RAID10:RAID1 + RAID0的結合,RAID1是一個冗余的備份陣列,RAID0是負責數據的讀寫陣列。例如:磁盤1和磁盤2組成一個Raid1,磁盤3和磁盤4又組成另外一個Raid1;這兩個Raid1組成了一個新的Raid0。其中磁盤1和磁盤2的數據是相互備份的,磁盤3和磁盤4的數據是相互備份的。
3.6 為Data和Journal/log分別使用單獨的物理卷
MongoDB很多的性能瓶頸和IO相關。建議為日志盤(Journal和MongoDB系統日志)單獨設定一個物理卷,減少對數據盤IO的資源占用。
MongoDB系統日志可以直接在命令行或者配置文件參數內指定。Journal日志不支持直接指定到另外的目錄,可以通過對Journal目錄創建symbol link的方式來解決。
如,/resource目錄和 /opt目錄分別是兩個不同的物理磁盤,
data存儲數據設置在 /resource 目錄,通過如下配置參數設置
Journal和log數據設置在 /opt 目錄,通過如下配置參數設置
Journal日志是MongoDB的預讀寫日志,用於數據庫崩潰時的數據恢復,可以在配置文件配置參數禁掉,通常生產環境不建議禁掉。Journal一般是在data存儲目錄下,通過創建軟連接symbol link來把路徑引到/opt目錄下
ln -s /resource/mongodbCluster/shard1/data/journal /opt/mongodbCluster/shard1/journal
3.7 禁用NUMA
非一致存儲訪問結構(NUMA:Non-Uniform Memory Access)是最新的內存管理技術。在一個使用NUMA技術的多處理器Linux系統上,當內存不足時,會采用SWAP的方式來獲得內存,而SWAP會導致數據庫性能急劇下降,所以應該禁止NUMA的使用。另外,MongoDB在NUMA環境下運行性能有時候可能會變慢,特別是在進程負載很高的情況下。
禁用NUMA的方法,在mongod前面加“numactl --interleave=all”:
numactl --interleave=all /opt/app/mongodb/bin/mongod -f /opt/app/mongodbCluster/conf/config.conf
3.8 設置vm.swappiness
vm.swappiness是操作系統控制物理內存交換出去的策略。它允許的值是一個百分比的值,最小為0,最大為100,該值默認為60.
vm.swappiness設置為0表示盡量少swap,100表示盡量將inactive的內存頁交換出去。
具體的說,當內存基本用滿的時候,系統會根據這個參數來判斷是把內存中很少用到的inactive內存交換出去,還是釋放數據的cache。cache中緩存着從磁盤讀出來的數據,根據程序的局部性原理,這些數據有可能在接下來又要被讀取;inactive內存顧名思義,就是那些被應用程序映射着,但是“長時間”不用的內存。
我們可以利用vmstat看到inactive的內存數量,也可以通過 /proc/meminfo 看到更詳細的信息:
MonogDB本身也是一個內存使用量較大的數據庫,它占用的內存比較多,不經常訪問的內存也會不少,這些內存如果被linux錯誤的交換出去了,將浪費很多CPU和IO資源,極大地降低數據庫的性能。如果vm.swappiness設置為0,會帶來內存溢出的問題,當內存不足時,會強制把某些程序kill掉。所以最好在MongoDB的服務器上設置vm.swappiness的值在1~10之間,盡可能少地使用swap。如果服務器內存比較大時,可以考慮設置vm.swappiness=0。
3.9 修改磁盤調度算法
對於磁盤I/O,Linux提供了Completely Fair Queuing(CFQ),Deadline scheduler和NOOP三種調度策略
目前Linux默認調度策略是CFQ,它聲稱對每一個IO請求都是公平的,這種調度策略對大部分應用都是適用的。但是如果數據庫有兩個請求,一個請求3次IO,一個請求10000次IO,由於絕對公平,3次IO的請求需要跟10000次IO的請求競爭,可能要等待上千個IO完成才能返回,導致它的響應時間非常慢。並且如果在處理的過程中,又有很多IO請求陸續發送過來,部分IO請求甚至可能一直無法得到調度被“餓死”。而Deadline scheduler調度策略則可以兼顧到一個請求不會在隊列中等待太久導致餓死,對數據庫這種應用來說更加適用。
暫時性設置,會失效:
echo deadline > /sys/block/sda/queue/scheduler
永久性設置,對於Centos6來說,在/etc/grub.conf的kernel行最后添加elevator=deadline來永久生效:
對於Centos7來說,執行如下命令:
grubby --update-kernel=ALL --args="elevator=deadline"
然后重啟生效。
注意:
一般Centos7默認支持的是deadline算法,而Centos6默認支持的cfq,而一般我們會在SSD硬盤環境中使用noop算法。
3.10 預讀值(readahead)設置
預讀值是文件操作系統的一個優化手段。Linux預讀默認256個扇區,大小為128K。MongoDB很多都是隨機訪問,對於隨機訪問,預讀值readhead應該設置較小為好。采用Linux的blockdev命令來把預讀readhead設置小一點,可以減少內存中無用數據占用,從而優化IO性能。RA代表預讀大小(扇區),推薦數值是16到32,如文檔較小,預讀數值可以小一點,修改后MongoDB重啟才能生效。
可以使用下述命令來顯示當前系統的預讀值:
暫時性更改預讀值,執行命令 blockdev --setra 32 /dev/sdb ,/dev/sdb為mongodb存儲的磁盤設備:
永久性更改,將 blockdev --setra 32 /dev/sdb 寫入配置文件/etc/rc.local,否則重啟就會失效:
3.11 設置Linux內核參數
打開/etc/sysctl.conf,在里面添加如下內容:
#並發連接backlog設置 net.core.somaxconn=32768 net.core.netdev_max_backlog=16384 net.core.rmem_default=262144 net.core.wmem_default=262144 net.core.rmem_max=16777216 net.core.wmem_max=16777216 net.core.optmem_max=16777216 #可用知名端口范圍: net.ipv4.ip_local_port_range='1024 65535' net.ipv4.tcp_max_syn_backlog=16384 #TCP Socket 讀寫 Buffer 設置: net.ipv4.tcp_rmem='1024 4096 16777216' net.ipv4.tcp_wmem='1024 4096 16777216'
添加完之后,不重啟更新:sysctl -p
4. 總結
參考資料:
http://www.ywnds.com/?p=8656
https://blog.csdn.net/liumiaocn/article/details/78877957
https://www.cnblogs.com/kerrycode/p/4743015.html
https://blog.csdn.net/yisun123456/article/details/78593909?utm_source=blogxgwz4
https://blog.csdn.net/yisun123456/article/details/78593832
http://www.mongoing.com/archives/8781
https://www.cnblogs.com/Joans/p/7723554.html
http://www.ywnds.com/?p=6502