最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解決mongo的tickets被耗盡導(dǎo)致卡頓問(wèn)題

 更新時(shí)間:2023年04月08日 15:04:20   作者:泰勒今天不想展開(kāi)  
這篇文章主要介紹了解決mongo的tickets被耗盡導(dǎo)致卡頓問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

近一年來(lái),項(xiàng)目線上環(huán)境的mongo數(shù)據(jù)庫(kù)出現(xiàn)多次tickets被耗盡,導(dǎo)致數(shù)據(jù)庫(kù)卡頓,并且都是突然出現(xiàn),等待一段時(shí)間后又能自動(dòng)恢復(fù)。

為了解決這個(gè)問(wèn)題,我們進(jìn)行了長(zhǎng)期的探索和研究,先后從多個(gè)角度進(jìn)行優(yōu)化,于此記錄和分享一下這一路的歷程。

tickets是什么

為了解決這個(gè)問(wèn)題,我們首先要明白ticktes是什么,其實(shí)網(wǎng)上基本都說(shuō)的一知半解,沒(méi)有一個(gè)能說(shuō)明白的,但是有一個(gè)查詢tieckts消耗情況的mongo命令:

db.serverStatus().wiredTiger.concurrentTransactions

查詢結(jié)果:

{
	"write" : {
		"out" : 0,
		"available" : 128,
		"totalTickets" : 128
	},
	"read" : {
		"out" : 1,
		"available" : 127,
		"totalTickets" : 128
	}
}

可以看到tickets分為讀寫(xiě)兩種,那ticktets到底是什么呢,我們根據(jù)這個(gè)查詢命令,其實(shí)大致可以猜測(cè)認(rèn)為是當(dāng)前同時(shí)存在的事務(wù)數(shù)量。

也就是mongo限制了同時(shí)進(jìn)行的事務(wù)數(shù)。

早期因?yàn)椴恢纓ickets到底是什么意思,嘗試過(guò)很多思路錯(cuò)誤的優(yōu)化,所以解決問(wèn)題,最好還是能弄明白問(wèn)題本身,才能對(duì)癥下藥。

思考?xì)v程

在眾多數(shù)據(jù)庫(kù)卡頓的經(jīng)歷中,曾有一次因?yàn)閞abbitmq導(dǎo)致的數(shù)據(jù)庫(kù)卡頓,原因是一小伙伴在請(qǐng)求的過(guò)濾層加了一個(gè)發(fā)送mq的邏輯,但是沒(méi)有進(jìn)行限制,導(dǎo)致每次只有有接口被調(diào),都會(huì)去發(fā)布一個(gè)mq消息,由于過(guò)高的并發(fā)導(dǎo)致rabbitmq不堪重負(fù),倒是讓人想不明到的是mq卡的同時(shí),數(shù)據(jù)庫(kù)也卡住了。

一開(kāi)始以為是因?yàn)橄⑦^(guò)多,導(dǎo)致消費(fèi)者瘋狂消費(fèi),壓垮了數(shù)據(jù)庫(kù),其實(shí)不存在這個(gè)問(wèn)題,因?yàn)槲覀兊膍q配置單個(gè)消費(fèi)者機(jī)器是串行的,也就是同一臺(tái)機(jī)器同一時(shí)間只會(huì)消費(fèi)同一個(gè)消息隊(duì)列的一條消息,所以并不會(huì)因?yàn)橄⒌亩嘟o數(shù)據(jù)庫(kù)帶來(lái)壓力,只會(huì)堆積在mq集群里。所以這次其實(shí)沒(méi)有找到mq卡頓導(dǎo)致mongo卡頓的原因。

我們接入的幾家第三方服務(wù),比如給我們提供IM消息服務(wù)的融云,每次他們出現(xiàn)問(wèn)題的時(shí)候,我們也會(huì)出現(xiàn)數(shù)據(jù)庫(kù)卡頓,并且每次時(shí)間出奇的一直,但也始終找不到原因。

起初經(jīng)過(guò)對(duì)他們調(diào)用我們接口情況進(jìn)行分析,發(fā)現(xiàn)每次他們出問(wèn)題時(shí),我們收到的請(qǐng)求會(huì)倍增,以為是這個(gè)原因?qū)е碌臄?shù)據(jù)庫(kù)壓力過(guò)大,并且我們基于redis和他們回調(diào)的流水號(hào)進(jìn)行了攔截,攔截方式如下:

  • 當(dāng)請(qǐng)求過(guò)來(lái)時(shí)從redis中查詢?cè)摴P流水號(hào)狀態(tài),如果狀態(tài)為已完結(jié),則直接成功返回
  • 如果查詢到狀態(tài)是進(jìn)行中,則拋異常給第三方,從而讓他繼續(xù)重試
  • 如果查詢不到狀態(tài),則嘗試設(shè)置狀態(tài)為進(jìn)行中并設(shè)置10秒左右的過(guò)期時(shí)間,如果設(shè)置成功,則放到數(shù)據(jù)庫(kù)層面進(jìn)行數(shù)據(jù)處理;如果設(shè)置失敗,也拋異常給第三方,等待下次重試
  • 等數(shù)據(jù)庫(kù)曾處理完成后,將redis中的流水號(hào)狀態(tài)改為已完結(jié)。

避免重復(fù)請(qǐng)求給我們帶來(lái)的數(shù)據(jù)庫(kù)的壓力。這其實(shí)也算是一部分原因但還是不算主要原因。

引起mongo卡頓的還有發(fā)布版本,有一段時(shí)間隔三差五發(fā)布版本,就會(huì)出現(xiàn)卡頓,但是查看更新的代碼也都是一些無(wú)關(guān)痛癢理論上不會(huì)引起問(wèn)題的內(nèi)容。

后來(lái)發(fā)現(xiàn)是發(fā)布版本時(shí)每次同時(shí)關(guān)閉和啟動(dòng)的機(jī)器從原來(lái)的一臺(tái)改成了兩臺(tái)(一臺(tái)一臺(tái)發(fā)布太慢,所以運(yùn)維改成了兩臺(tái)兩臺(tái)一起發(fā)),感覺(jué)原因應(yīng)該就在這里,后來(lái)想到會(huì)不會(huì)和優(yōu)雅關(guān)閉有關(guān),當(dāng)機(jī)器關(guān)閉時(shí)仍然有mq消費(fèi)者以及內(nèi)置循環(huán)腳本在執(zhí)行,當(dāng)進(jìn)程殺死時(shí),會(huì)產(chǎn)生大量需要立馬回滾的事務(wù),從而導(dǎo)致mongo卡頓。

后來(lái)經(jīng)過(guò)和運(yùn)維小伙伴的溝通發(fā)現(xiàn),在優(yōu)雅關(guān)閉方面確實(shí)存在問(wèn)題,他們關(guān)閉容器時(shí)會(huì)小容器內(nèi)的主進(jìn)程發(fā)一個(gè)容器即將關(guān)閉的信號(hào),然后等待幾十秒后,如果主進(jìn)程沒(méi)有自己關(guān)閉,則會(huì)直接殺死進(jìn)程。

為此我們需要在程序中實(shí)現(xiàn)對(duì)關(guān)閉信號(hào)的監(jiān)聽(tīng),并實(shí)現(xiàn)優(yōu)雅關(guān)閉的邏輯,在spring中,我們可以通過(guò)spring的時(shí)間拿到外部即將關(guān)閉的信號(hào):

	@Volatile
	private var consumeSwitch = true

	/**
	* 銷毀邏輯
	*/
	@EventListener
	fun close(event: ContextClosedEvent){
		consumeSwitch = false
		logger.info("----------------------rabbitmq停止消費(fèi)----------------------")
	}

可以通過(guò)如上方式,對(duì)系統(tǒng)中的mq消費(fèi)者或者其他內(nèi)置程序進(jìn)行優(yōu)雅關(guān)??刂疲瑢?duì)優(yōu)雅關(guān)閉問(wèn)題優(yōu)化后,服務(wù)器關(guān)閉重啟導(dǎo)致的數(shù)據(jù)庫(kù)卡頓確實(shí)得到了有效解決。

上面的融云問(wèn)題優(yōu)化過(guò)后,后來(lái)融云再次卡頓的時(shí)候,還是會(huì)出現(xiàn)mongo卡頓,由此可見(jiàn),肯定和第三方有關(guān),但上面說(shuō)的問(wèn)題肯定不是主要原因。

后來(lái)我看到我們調(diào)用第三方的邏輯很多都在@Transactional代碼塊中間,后來(lái)去看了第三方sdk里的邏輯,其實(shí)就是封裝了一個(gè)http請(qǐng)求,但是http請(qǐng)求的請(qǐng)求超時(shí)時(shí)間長(zhǎng)達(dá)60秒,那就會(huì)有一個(gè)問(wèn)題,如果這個(gè)時(shí)候第三方服務(wù)器卡頓了,這個(gè)請(qǐng)求就會(huì)不斷地等,知道60s超時(shí),而由于這個(gè)操作是在事務(wù)塊中,意味著這個(gè)事務(wù)也不會(huì)commit掉,那等于這個(gè)事務(wù)所占用的tickets也一直不會(huì)放掉,至此根本原因似乎找到了,是因?yàn)槭聞?wù)本身被卡住了,導(dǎo)致tickets耗盡,從而后面新的事務(wù)全部都在等待狀態(tài),全部都卡住了。

其實(shí)這次找的原因,同樣也可以解釋前面mq卡頓導(dǎo)致的數(shù)據(jù)庫(kù)卡頓,因?yàn)橥瑯佑写罅康陌l(fā)送mq的操作在事務(wù)塊中,因?yàn)槎虝r(shí)間瘋狂發(fā)mq,導(dǎo)致mq服務(wù)端卡頓,從而導(dǎo)致發(fā)mq的操作出現(xiàn)卡頓,這就會(huì)出現(xiàn)整個(gè)事務(wù)被卡住,接著tickets被消耗殆盡,整個(gè)數(shù)據(jù)庫(kù)卡頓。

找到確定問(wèn)題后就好對(duì)癥下藥了,第三方的問(wèn)題由于我們不能保證第三方的穩(wěn)定性,所以當(dāng)?shù)谌匠霈F(xiàn)問(wèn)題時(shí)的思路應(yīng)該是進(jìn)行服務(wù)降級(jí),允許部分功能不可用,確定核心業(yè)務(wù)不受影響,我們基于java線程池進(jìn)行了同步改異步處理,并且由于第三方的工作是給用戶推送im消息,所以配置的舍棄策略是當(dāng)阻塞隊(duì)列堆積滿之后,將最老的進(jìn)行丟棄。

而如果是mq導(dǎo)致的這種情況,我們這邊沒(méi)有進(jìn)行額外的處理,因?yàn)檫@種情況是有自身的bug導(dǎo)致的,這需要做好整理分享工作,避免再次出現(xiàn)這樣的bug。

//自己實(shí)現(xiàn)的runnable
abstract class RongCloudRunnable(
	private val taskDesc: String,
	private val params: Map<String, Any?>
	) : Runnable {


	override fun toString(): String {
		return "任務(wù)名稱:${taskDesc};任務(wù)參數(shù):${params}"
	}
}		
//構(gòu)建線程池
private val rongCloudThreadPool = ThreadPoolExecutor(
	externalProps.rongCloud.threadPoolCoreCnt, externalProps.rongCloud.threadPoolMaxCnt, 5,
	TimeUnit.MINUTES, LinkedBlockingQueue<Runnable>(externalProps.rongCloud.threadPoolQueueLength),
	RejectedExecutionHandler { r, executor ->
		if (!executor.isShutdown) {
			val item = executor.queue.poll()
			logger.warn("當(dāng)前融云阻塞任務(wù)過(guò)多,舍棄最老的任務(wù):${item}")
			executor.execute(r)
		}
	}
)

//封裝線程池任務(wù)處理方法
fun taskExecute(taskDesc: String, params: Map<String,Any?>, handle: ()-> Unit){
	rongCloudThreadPool.execute(object :RongCloudRunnable(taskDesc, params){
		override fun run() {
			handle()
		}
	})
}

//具體使用
taskExecute("發(fā)送消息", mapOf(
	"from_id" to fromId,
	"target_ids" to targetIds,
	"data" to data,
	"is_include_sender" to isIncludeSender
)){
	sendMessage(BatchSendData(fromId, targetIds, data, isIncludeSender))
}		

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • MongoDB Shell 命令實(shí)例總結(jié)【進(jìn)階篇】

    MongoDB Shell 命令實(shí)例總結(jié)【進(jìn)階篇】

    這篇文章主要介紹了MongoDB Shell 命令,結(jié)合實(shí)例形式總結(jié)分析了MongoDB數(shù)據(jù)庫(kù)常用的查詢、更新、插入、集合、函數(shù)等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2019-02-02
  • mongodb主從同步配置實(shí)戰(zhàn)詳細(xì)教程(建議收藏)

    mongodb主從同步配置實(shí)戰(zhàn)詳細(xì)教程(建議收藏)

    MongoDB主從同步是一種數(shù)據(jù)庫(kù)同步備份技術(shù),主要用于數(shù)據(jù)備份、故障恢復(fù)和讀擴(kuò)展,其基本原理是通過(guò)主節(jié)點(diǎn)記錄操作日志,從節(jié)點(diǎn)定期獲取這些日志并在本地執(zhí)行,實(shí)現(xiàn)數(shù)據(jù)的同步,適合需要高可用性的系統(tǒng)部署,感興趣的朋友一起看看吧
    2022-02-02
  • MongoDB 常用命令總結(jié)

    MongoDB 常用命令總結(jié)

    Mongo最大的特點(diǎn)是他支持的查詢語(yǔ)言非常強(qiáng)大,其語(yǔ)法有點(diǎn)類似于面向?qū)ο蟮牟樵冋Z(yǔ)言,幾乎可以實(shí)現(xiàn)類似關(guān)系數(shù)據(jù)庫(kù)單表查詢的絕大部分功能,而且還支持對(duì)數(shù)據(jù)建立索引。Mongo還可以解決海量數(shù)據(jù)的查詢效率,當(dāng)數(shù)據(jù)量達(dá)到50GB以上時(shí),Mongo數(shù)據(jù)庫(kù)訪問(wèn)速度是MySQL10 倍以上
    2015-05-05
  • Mongodb的oplog詳解

    Mongodb的oplog詳解

    這篇文章主要介紹了Mongodb的oplog詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • MongoDB 刪除文檔的方式(刪除一個(gè)、批量刪除)

    MongoDB 刪除文檔的方式(刪除一個(gè)、批量刪除)

    這篇文章主要介紹了MongoDB 刪除文檔的方式(刪除一個(gè)、批量刪除),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • MongoDB高可用與分片

    MongoDB高可用與分片

    最近項(xiàng)目在使用MongoDB作為圖片和文檔的存儲(chǔ)數(shù)據(jù)庫(kù),為啥不直接存MySQL里,還要搭個(gè)MongoDB集群,麻不麻煩?讓我們一起,一探究竟,繼續(xù)學(xué)習(xí)MongoDB高可用和片鍵策略,實(shí)現(xiàn)快速入門,感興趣的小伙伴可以參考閱讀
    2023-04-04
  • mongodb基礎(chǔ)入門_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    mongodb基礎(chǔ)入門_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了mongodb基礎(chǔ)入門的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • 詳解MongoDB4.0構(gòu)建分布式分片群集

    詳解MongoDB4.0構(gòu)建分布式分片群集

    這篇文章主要介紹了詳解MongoDB4.0構(gòu)建分布式分片群集,詳細(xì)的介紹了什么是MongoDB分片和具體使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • MongoDB 3.6.5常見(jiàn)的安裝失敗原因和解決辦法

    MongoDB 3.6.5常見(jiàn)的安裝失敗原因和解決辦法

    在開(kāi)發(fā)過(guò)程中,可能會(huì)用到 MongoDB 數(shù)據(jù)庫(kù),在進(jìn)行MongoDB的安裝過(guò)程中,可能會(huì)遇到各種各樣的問(wèn)題導(dǎo)致安裝失敗,本文將針對(duì)常見(jiàn)的安裝失敗情況(,例如端口占用、系統(tǒng)文件問(wèn)題和版本兼容問(wèn)題等)進(jìn)行分析,并提供解決方案和相應(yīng)的代碼示例
    2024-03-03
  • 解決MAC上啟動(dòng)mongod報(bào)錯(cuò)exiting with code 1的問(wèn)題

    解決MAC上啟動(dòng)mongod報(bào)錯(cuò)exiting with code 1的問(wèn)題

    這篇文章主要介紹了解決MAC上啟動(dòng)mongod報(bào)錯(cuò)exiting with code 1的問(wèn)題,本文給大家介紹的非常詳細(xì)對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12

最新評(píng)論

宿州市| 舒兰市| 皮山县| 英德市| 成武县| 临漳县| 丽水市| 凌云县| 泾源县| 尼木县| 育儿| 筠连县| 绥中县| 星座| 宁城县| 叶城县| 崇明县| 抚松县| 西平县| 台北县| 东源县| 建德市| 怀安县| 威海市| 澄江县| 古浪县| 定南县| 庆阳市| 常熟市| 长泰县| 湄潭县| 彩票| 玉田县| 叙永县| 酒泉市| 英吉沙县| 定南县| 宁陕县| 玉树县| 永修县| 汤阴县|