MongoDB監控之一:運行狀態、性能監控,分析


為什么要監控?

監控及時獲得應用的運行狀態信息,在問題出現時及時發現。

監控什么?

CPU、內存、磁盤I/O、應用程序(MongoDB)、進程監控(ps -aux)、錯誤日志監控

1.4.1 MongoDB集群監控方式

db.serverStatus()

  查看實例運行狀態(內存使用、鎖、用戶連接等信息)

  通過比對前后快照進行性能分析

復制代碼
"connections"     # 當前連接到本機處於活動狀態的連接數
"activeClients"   # 連接到當前實例處於活動狀態的客戶端數量
"locks"           # 鎖相關參數
"opcounters"      # 啟動之后的參數
"opcountersRepl"  # 復制想關
"storageEngine"   # 查看數據庫的存儲引擎
"mem"             # 內存相關
復制代碼

狀態:

db.stats()

顯示信息說明:

復制代碼
# 統計數據庫信息
db.stats()
{
        "db" : "test",          # 系統自帶測試數據庫
        "collections" : 0,      # 集合數量
        "views" : 0,            #
        "objects" : 0,          # 文檔對象的個數, 所有集合的記錄數之和
        "avgObjSize" : 0,         # 平均每個對象的大小, 通過 dataSize / Objects 得到
        "dataSize" : 0,         # 當前庫所有集合的數據大小
        "storageSize" : 0,       # 磁盤存儲大小
        "numExtents" : 0,        # 所有集合的擴展數據量統計數
        "indexes" : 0,            # 已建立索引數量
        "indexSize" : 0,        # 索引大小
        "fileSize" : 0,            #
        "fsUsedSize" : 0,        #
        "fsTotalSize" : 0,        #總大小
        "ok" : 1
}
復制代碼

1.4.2 mongostat

mongostat是mongdb自帶的狀態檢測工具,在命令行下使用。它會間隔固定時間獲取mongodb的當前運行狀態,並輸出。如果你發現數據庫突然變慢或者有其他問題的話,你第一手的操作就考慮采用mongostat來查看mongo的狀態。

主要功能:

實時數據庫狀態,讀寫、加鎖、索引命中、缺頁中斷、讀寫等待隊列等情況。

每秒刷新一次狀態值,並能提供良好的可讀性,通過這些參數可以觀察到MongoDB系統整體性能情況。

常用命令格式:

mongostat --host 192.168.1.100:27017 -uroot -p123456 --authenticationDatabase admin
參數說明:
host:指定IP地址和端口,也可以只寫IP,然后使用--port參數指定端口號
-u: 如果開啟了認證,則需要在其后填寫用戶名
-p: 不用多少,肯定是密碼
--authenticationDatabase:若開啟了認證,則需要在此參數后填寫認證庫(注意是認證上述賬號的數據庫)
輸出各字段解釋說明:
insert/s : 官方解釋是每秒插入數據庫的對象數量,如果是slave,則數值前有*,則表示復制集操作
query/s : 每秒的查詢操作次數
update/s : 每秒的更新操作次數
delete/s : 每秒的刪除操作次數
getmore/s: 每秒查詢cursor(游標)時的getmore操作數
command: 每秒執行的命令數,在主從系統中會顯示兩個值(例如 3|0),分表代表 本地|復制 命令
注: 一秒內執行的命令數比如批量插入,只認為是一條命令(所以意義應該不大)
dirty: 僅僅針對WiredTiger引擎,官網解釋是臟數據字節的緩存百分比
used:僅僅針對WiredTiger引擎,官網解釋是正在使用中的緩存百分比
flushes:
For WiredTiger引擎:指checkpoint的觸發次數在一個輪詢間隔期間
For MMAPv1 引擎:每秒執行fsync將數據寫入硬盤的次數
注:一般都是0,間斷性會是1, 通過計算兩個1之間的間隔時間,可以大致了解多長時間flush一次。flush開銷是很大的,如果頻繁的flush,可能就要找找原因了
vsize:  虛擬內存使用量,單位MB (這是 在mongostat 最后一次調用的總數據)
res:   物理內存使用量,單位MB (這是 在mongostat 最后一次調用的總數據)
注:這個和你用top看到的一樣, vsize一般不會有大的變動, res會慢慢的上升,如果res經常突然下降,去查查是否有別的程序狂吃內存。
 
qr: 客戶端等待從MongoDB實例讀數據的隊列長度
qw:客戶端等待從MongoDB實例寫入數據的隊列長度
ar: 執行讀操作的活躍客戶端數量
aw: 執行寫操作的活客戶端數量
注:如果這兩個數值很大,那么就是DB被堵住了,DB的處理速度不及請求速度。看看是否有開銷很大的慢查詢。如果查詢一切正常,確實是負載很大,就需要加機器了
netIn:MongoDB實例的網絡進流量
netOut:MongoDB實例的網絡出流量
注:此兩項字段表名網絡帶寬壓力,一般情況下,不會成為瓶頸
conn: 打開連接的總數,是qr,qw,ar,aw的總和
注:MongoDB為每一個連接創建一個線程,線程的創建與釋放也會有開銷,所以盡量要適當配置連接數的啟動參數,maxIncomingConnections,阿里工程師建議在5000以下,基本滿足多數場景。

 

1.4.3 mongotop

mongotop命令說明:

復制代碼
[mongod@MongoDB oplog]$ mongotop  -h 127.0.0.1:27017
2018-01-08T17:32:56.623+0800    connected to: 127.0.0.1:27017

                                               ns    total    read    write    2018-01-08T17:32:57+08:00
                               admin.system.roles      0ms     0ms      0ms                             
                               admin.system.users      0ms     0ms      0ms                             
                             admin.system.version      0ms     0ms      0ms                             
                                         app.user      0ms     0ms      0ms                             
             automationcore.automation.job.status      0ms     0ms      0ms                             
                 automationcore.config.automation      0ms     0ms      0ms                             
        automationcore.config.automationTemplates      0ms     0ms      0ms                             
automationcore.config.automationTemplates_archive      0ms     0ms      0ms                             
         automationcore.config.automation_archive      0ms     0ms      0ms                             
                 automationstatus.lastAgentStatus      0ms     0ms      0ms      
復制代碼

mongotop重要指標

ns:數據庫命名空間,后者結合了數據庫名稱和集合。
total:mongod在這個命令空間上花費的總時間。
read:在這個命令空間上mongod執行讀操作花費的時間。
write:在這個命名空間上mongod進行寫操作花費的時間。

1.4.3 mongosniff

此工具可以從底層監控到底有哪些命令發送給了MongoDB 去執行,從中就可以進行分析:以root 身份執行:

$./mongosniff --source NET lo

然后其會監控位到本地以localhost 監聽默認27017 端口的MongoDB 的所有包請求。

 

1.4.3 db級別命令

1、db.currentOp()

db.currentOp是個好東西,顧名思義,就是當前的操作。在mongodb中可以查看當前數據庫上此刻的操作語句信息,包括insert/query/update/remove/getmore/command等多種操作。直接執行

db.currentOp()一般返回一個空的數組,我們可以指定一個參數true,這樣就返回用戶connections與系統cmmand相關的操作。下面看個列子:

db.currentOp(true) 會返回很多信息:

db.currentOp()

查看數據庫當前執行什么操作。

用於查看長時間運行進程。

通過(執行時長、操作、鎖、等待鎖時長)等條件過濾。

重點關注以下幾個字段:

 

字段 說明
client 請求是由哪個客戶端發起的。
opid 操作的opid,有需要的話,可以通過db.killOp(opid) 直接終止該操作。
secs_running/microsecs_running 這個值重點關注,代表請求運行的時間,如果這個值特別大,請看看請求是否合理。
query/ns 這個字段能看出是對哪個集合正在執行什么操作。
lock* - 還有一些跟鎖相關的參數,需要了解可以看官網文檔,本文不做詳細介紹。
- db.currentOp文檔請參見:db.currentOp 

示例:

 

gechongrepl:PRIMARY> db.currentOp()
{
    "inprog" : [
        {
            "opid" : 6222,
            "active" : true,
            "secs_running" : 3,
            "microsecs_running" : NumberLong(3662328),
            "op" : "getmore",
            "ns" : "local.oplog.rs",
            "query" : {
                 
            },
            "client" : "192.168.91.132:45745",
            "desc" : "conn5",
            "threadId" : "0x7f1370cb4700",
            "connectionId" : 5,
            "waitingForLock" : false,
            "numYields" : 0,
            "lockStats" : {
                "timeLockedMicros" : {
                    "r" : NumberLong(141),
                    "w" : NumberLong(0)
                },
                "timeAcquiringMicros" : {
                    "r" : NumberLong(16),
                    "w" : NumberLong(0)
                }
            }
        }
    ]
}

 

opid" : 6222,#進程號
"active" : true,#是否活動狀態
"secs_running" : 3,#操作運行了多少秒
"microsecs_running" : NumberLong(3662328),
"op" : "getmore",#操作類型,包括(insert/query/update/remove/getmore/command)
"ns" : "local.oplog.rs",#命名空間
"query" : {},#如果op是查詢操作,這里將顯示查詢內容;也有說這里顯示具體的操作語句的

"client" : "192.168.91.132:45745",#連接的客戶端信息
"desc" : "conn5",#數據庫的連接信息
"threadId" : "0x7f1370cb4700",#線程ID
"connectionId" : 5,#數據庫的連接ID
"waitingForLock" : false,#是否等待獲取鎖
"numYields" : 0,
"lockStats" : {
"timeLockedMicros" : {#持有的鎖時間微秒
"r" : NumberLong(141),#整個MongoDB實例的全局讀鎖
"w" : NumberLong(0)},#整個MongoDB實例的全局寫鎖
"timeAcquiringMicros" : {#為了獲得鎖,等待的微秒時間
"r" : NumberLong(16),#整個MongoDB實例的全局讀鎖
"w" : NumberLong(0)}#整個MongoDB實例的全局寫鎖

 

2、db.killOp(opid)

kill當前的操作 opid為具體的操作id號,當然了,只能kill正在進行中的。opid是通過db.currentOp()查詢返回的。如果發現一個操作太長,把數據庫卡死的話,可以用這個命令殺死他:> db.killOp(608605)

示例:

復制代碼
 { "inprog" :   
        [   
            {  
                        "opid" : 3434473,//操作的id "active" : <boolean>,//是否處於活動狀態 "secs_running" : 0,//操作運行了多少秒 "op" : "<operation>",//具體的操作行為,包括(insert/query/update/remove/getmore/command) "ns" : "<database>.<collection>",//操作的命名空間,如:數據庫名.集合名 "query" : {//具體的操作語句  }, "client" : "<host>:<outgoing>",//連接的客戶端信息 "desc" : "conn57683",//數據庫連接描述 "threadId" : "0x7f04a637b700",//線程id "connectionId" : 57683,//數據庫連接id "locks" : {//鎖的相關信息 "^" : "w", "^local" : "W", "^<database>" : "W" }, "waitingForLock" : false,//是否在等待並獲取鎖, "msg": "<string>" "numYields" : 0, "progress" : { "done" : <number>, "total" : <number> } "lockStats" : { "timeLockedMicros" : {//此操作獲得以下鎖后,把持的微秒時間 "R" : NumberLong(),//整個mongodb服務實例的全局讀鎖 "W" : NumberLong(),//整個mongodb服務實例的全局寫鎖 "r" : NumberLong(),//某個數據庫實例的讀鎖 "w" : NumberLong() //某個數據庫實例的寫鎖  }, "timeAcquiringMicros" : {//此操作為了獲得以下的鎖,而耗費等待的微秒時間 "R" : NumberLong(),//整個mongodb服務實例的全局讀鎖 "W" : NumberLong(),//整個mongodb服務實例的全局寫鎖 "r" : NumberLong(),//某個數據庫實例的讀鎖 "w" : NumberLong()//某個數據庫實例的寫鎖  } } }, ..... ] }
復制代碼

1.4.3 MongoDB優化器profile

在MySQL 中,慢查詢日志是經常作為我們優化數據庫的依據,那在MongoDB 中是否有類似的功能呢?答案是肯定的,那就是MongoDB Database Profiler。

1.開啟profiling功能

有兩種方式可以控制 Profiling 的開關和級別,第一種是直接在啟動參數里直接進行設置。啟動MongoDB 時加上–profile=級別 即可。也可以在客戶端調用db.setProfilingLevel(級別) 命令來實時配置,Profiler 信息保存在system.profile 中。我們可以通過db.getProfilingLevel()命令來獲取當前的Profile 級別,類似如下操作:

db.setProfilingLevel(2);

上面profile 的級別可以取0,1,2 三個值,他們表示的意義如下:

0 – 不開啟

1 – 記錄慢命令 (默認為>100ms)

2 – 記錄所有命令

Profile 記錄在級別1 時會記錄慢命令,那么這個慢的定義是什么?上面我們說到其默認為100ms,當然有默認就有設置,其設置方法和級別一樣有兩種,一種是通過添加 –slowms 啟動參數配置。第二種是調用db.setProfilingLevel 時加上第二個參數:

db.setProfilingLevel( level , slowms )
db.setProfilingLevel( 1 , 10 );

2.查看 Profile的設置級別

db.getProfilingLevel()

> db.setProfilingLevel(1)
{ "was" : 2, "slowms" : 100, "sampleRate" : 1, "ok" : 1 } > db.getProfilingLevel() 1 >

3.查詢 Profiling 記錄

與MySQL的慢查詢日志不同,Mongo Profile 記錄是直接存在系統db里的,記錄位置 system.profile ,所以,我們只要查詢這個Collection的記錄就可以獲取到我們的 Profile 記錄了。

慢查詢(system.profile)說明

詳細信息見《MongoDB分析工具之二:MongoDB分析器Profile

二、性能問題排查

2.1、mongodb client端報錯,感覺像連接數配置小了

mongoDB server端定位方法:

查看總的連接數,因為mongoDB 默認的最大連接數為820.

netstat -nat | grep -i "27017" | wc -l

netstat -nt|grep 27017|wc -l

或者:

到/data/mongodb/mongos/log

查看mongoDB的日志文件:
mongos.diagnostic.data  mongos.log

2.2、設置mongoDB server的最大連接數

修改mongodb最大連接數

在啟動里邊加參數  --maxConns=20000或者在 /etc/mongod.cnf (我自己見的配置文件添加 maxConns=20000)

重啟mongodb

如果當前mongodb最大連接數沒有變成20000,排查你service mongodb啟動的腳本,如果腳本有 ulimit -n 12000,修改成30000,

如果修改成20000,貌似最大連接數也不到20000,這里具體原因沒查,我的腳本是 /etc/init.d/mongod

還有一個地方可能影響到mongodb最大連接數,Linux系統默認一個進程最大打開文件數目是1024,修改rc.local

vi /etc/rc.local

很好我這里的一個進程最大打開文件數目遠遠大於20000

2.3、報錯:because there was a socket exception raised by this connection.

回答1:

After few tries I've found out that it was a problem with the Azure's Load Balancer.
After 60s of inactivity it will disconnect any pending TCP connection.

After further digging I've found this post of the MongoDB diagnostics FAQ, and I've set the tcp keepalive to 120s:

sudo sysctl -w net.ipv4.tcp_keepalive_time=<value>

and I've also set the socketKeepAlive of the MongoClient to true:

MongoClientOptions.Builder options = MongoClientOptions.builder(); options.socketKeepAlive(true); mongoClient = new MongoClient(mongoAddress, options.build());

After these fixes the issue seems gone!

回答2:

If you experience socket errors between clients and servers or between members of a sharded cluster or replica set that do not have other reasonable causes, check the TCP keepalive value (for example, the tcp_keepalive_time value on Linux systems). A common keepalive period is 7200 seconds (2 hours); however, different distributions and macOS may have different settings.

For MongoDB, you will have better results with shorter keepalive periods, on the order of 120 seconds (two minutes).

where u have installed mongodb u have to simply run this command on Linux

sudo sysctl -w net.ipv4.tcp_keepalive_time=120

 

mtop – 針對 MongoDB 的 top 命令

這是一個基於MongoDB Python 客戶端 pymongo 的小程序,他使你可以像用操作系統的top命令一樣,實時觀察你的MongoDB 的狀態。

1.安裝 pymongo 及 mtop

下載安裝pymongo:http://api.mongodb.org/python/1.9%2B/installation.html

如果有easy_install 那安裝起來就比較easy了~只需要:

$ easy_install pymongo

下載安裝mtop:https://github.com/beaufour/mtop

2.運行mtop

./mtop.py -s localhost:27017 -d 2000

3.參數說明

  • -s:表示MongoDB 所在的機器及端口
  • -d:刷新的間隔,以毫秒計所以上面表示每兩秒一次。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM