共計(jì) 2848 個(gè)字符,預(yù)計(jì)需要花費(fèi) 8 分鐘才能閱讀完成。
這篇文章給大家分享的是有關(guān) Mongo 中如何使用 killOp 干掉 Long Running Operation 的內(nèi)容。丸趣 TV 小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨丸趣 TV 小編過來看看吧。
詳解:
詳解 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,# 進(jìn)程號(hào)
active : true,# 是否活動(dòng)狀態(tài)
secs_running : 3,# 操作運(yùn)行了多少秒
microsecs_running : NumberLong(3662328),
op : getmore ,# 操作類型,包括 (insert/query/update/remove/getmore/command)
ns : local.oplog.rs ,# 命名空間
query : {},# 如果 op 是查詢操作,這里將顯示查詢內(nèi)容;也有說這里顯示具體的操作語句的
client : 192.168.91.132:45745 ,# 連接的客戶端信息
desc : conn5 ,# 數(shù)據(jù)庫的連接信息
threadId : 0x7f1370cb4700 ,# 線程 ID
connectionId : 5,# 數(shù)據(jù)庫的連接 ID
waitingForLock : false,# 是否等待獲取鎖
numYields : 0,
lockStats : {
timeLockedMicros : {# 持有的鎖時(shí)間微秒
r : NumberLong(141),# 整個(gè) MongoDB 實(shí)例的全局讀鎖
w : NumberLong(0)},# 整個(gè) MongoDB 實(shí)例的全局寫鎖
timeAcquiringMicros : {# 為了獲得鎖,等待的微秒時(shí)間
r : NumberLong(16),# 整個(gè) MongoDB 實(shí)例的全局讀鎖
w : NumberLong(0)}# 整個(gè) MongoDB 實(shí)例的全局寫鎖
MongoDB 提供了 killOp 請(qǐng)求,用于干掉運(yùn)行時(shí)間很長的請(qǐng)求,killOp 通常需要與 currentOp 組合起來使用;先根據(jù) currentOp 查詢到請(qǐng)求的 opid,然后根據(jù) opid 發(fā)送 killOp 的請(qǐng)求。
currentOp
currentOp 的使用,參考官方文檔
currentOp 會(huì)將后端 Mongod 上正在執(zhí)行的請(qǐng)求都列出來,也可根據(jù)查詢條件(如請(qǐng)求類型,請(qǐng)求是否正在等待鎖,請(qǐng)求操作的 DB 或 collection)來進(jìn)行過濾。
例 1:查詢所有正在等待鎖的寫操作
db.currentOp(
{
waitingForLock : true,
$or: [ { op : { $in : [ insert , update , remove ] } },
{ query.findandmodify : { $exists: true } }
]
}
)
例 2:查詢所有操作 db1 并且執(zhí)行時(shí)間已超過 3s 的請(qǐng)求
db.currentOp(
{
active : true,
secs_running : { $gt : 3 },
ns : /^db1\./
}
)
currentOp 的過濾條件包括
請(qǐng)求操作類型,insert、update、delete…
請(qǐng)求對(duì)應(yīng)的 connectionId,threadId
請(qǐng)求是否正在等待鎖
請(qǐng)求執(zhí)行時(shí)間
請(qǐng)求操作的 DB 或 collection
請(qǐng)求 query 的內(nèi)容
…
killOp
currentOp 的輸出結(jié)果里,每個(gè)請(qǐng)求包含一個(gè) opid 字段,有了 opid,就可以發(fā)送 killOp 來干掉對(duì)應(yīng)的請(qǐng)求。
db.killOp(opid)
要了解 killOp 的意義,需要先搞清楚幾個(gè)問題
客戶端到 Monogd Server 連接斷掉后,連接上執(zhí)行的請(qǐng)求是否會(huì)立即結(jié)束?
比如你通過 mongo shell,發(fā)送了一個(gè) createIndex 的請(qǐng)求,給某個(gè)包含 1000w 個(gè)文檔的集合建立索引,這個(gè)請(qǐng)求會(huì)耗時(shí)很久,你想提前中止請(qǐng)求,Ctrl- C 停掉了 mongo shell,此時(shí) mongo shell 到 server 的連接會(huì)關(guān)閉掉。
但后端 createIndex 的請(qǐng)求(MongoDB 每個(gè)連接的請(qǐng)求由一個(gè)對(duì)應(yīng)的線程來處理)不會(huì)立即結(jié)束,而是會(huì)一直執(zhí)行下去,直到 createIndex 結(jié)束,給客戶端發(fā)送應(yīng)答時(shí),發(fā)現(xiàn)連接已經(jīng)關(guān)閉,然后線程才退出。
為了讓 createIndex 早點(diǎn)結(jié)束,你就需要 killOp 來幫忙,通過 currentOp 找到 craeteIndex 請(qǐng)求的 opid,然后發(fā)送 killOp,createIndex 會(huì)在下個(gè)『檢查點(diǎn)』就結(jié)束執(zhí)行,整個(gè)線程退出。
發(fā)送 killOp 后,請(qǐng)求是否會(huì)立即結(jié)束?
killOp 的實(shí)現(xiàn)原理如下
每個(gè)連接對(duì)應(yīng)的服務(wù)線程存儲(chǔ)了一個(gè) killPending 的字段,當(dāng)發(fā)送 killOp 時(shí),會(huì)將該字段置 1;請(qǐng)求在執(zhí)行過程中,可以通過不斷的調(diào)用 OperationContext::checkForInterrupt() 來檢查 killPending 是否被設(shè)置,如果被設(shè)置,則線程退出。
一個(gè)請(qǐng)求要支持 killOp,必須在請(qǐng)求的處理邏輯里加上 checkForInterrupt() 檢查點(diǎn)才行,否則即使發(fā)送了 killOp,也只能等待請(qǐng)求完全處理完畢線程才會(huì)退出。
比如 createIndex 的處理邏輯里包含了類似如下的代碼,在 createIndex 的循環(huán)過程中,一旦 killPending 被置 1 了,createIndex 的執(zhí)行可以在當(dāng)前循環(huán)結(jié)束時(shí)退出。
while (!createIndexFinished) { createIndexForOneElement();
checkForInterupt();}
所以發(fā)送 killOp 后,請(qǐng)求要執(zhí)行到下一個(gè)『檢查點(diǎn)』線程才會(huì)退出,MongoDB 在很多可能耗時(shí)長的請(qǐng)求中,都加入了 checkForInterrupt() 檢查點(diǎn),如創(chuàng)建索引,repair database,mapreduce、aggregation 等。
感謝各位的閱讀!關(guān)于“Mongo 中如何使用 killOp 干掉 Long Running Operation”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!