日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

巧用 maxTimeMS 服务端超时,避免承载亿级用户的腾讯云数据库MongoDB服务雪崩

發布時間:2024/2/28 数据库 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 巧用 maxTimeMS 服务端超时,避免承载亿级用户的腾讯云数据库MongoDB服务雪崩 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

騰訊云數據庫MongoDB作為一款基于開源社區MongoDB版本的文檔數據庫產品,其承載著公司內外包括微信、看點、QQ音樂在內的億級用戶重量級APP產品。在某些場景的使用過程中,用戶在客戶端請求超時后會不斷重試,可能導致服務端大量請求積壓,出現惡性循環甚至導致服務雪崩。一般遇到這種情況,后臺會自動檢測并做服務降級,主動拒絕一部分用戶請求,或者重啟后端服務等舉措來應對。但是這些措施對業務有損,或者不可自行恢復。

本文圍繞 MongoDB 原生 maxTimeMS 特性和騰訊云MongoDB的優化,并結合 4.0 版本代碼,詳細闡述如何巧用 maxTimeMS 服務端超時,來避免服務端請求積壓導致雪崩的情形。

背景

業務方在騰訊云MongoDB運營過程中,曾有業務集群出現過:慢請求 -> 客戶端斷開重試 -> 服務端累積的請求越來越多 -> 服務雪崩 -> 人工重啟解決的問題。

過去,為了防止服務雪崩,騰訊云MongoDB應對的解決方案是:在內核中實現了連接狀態檢測、自適應限流等功能進行過載保護,并開發了外圍工具 kill 長時間運行的請求等。但是過載保護本質上會進行服務降級,對業務還是會產生一定影響,而外圍工具處理起來也不夠及時,甚至可能在節點 hang 住時無法工作,以上解決舉措都存在著一定程度的弊端。

為了更好地避免服務雪崩,騰訊云MongoDB建議設置服務端超時,并和客戶端超時保持一致。這樣在客戶端出現超時后,服務端也立刻終止這些“無意義”請求的執行。通過避免服務端資源的無效占用,極大地降低客戶端不斷重試導致服務雪崩的概率。

MongoDB原生服務端超時原理

當一個用戶請求到達 mongos 或者 mongod 時,會生成一個對應的 OperationContext 對象,來記錄這個請求從開始到結束期間的完整上下文信息。上下文信息中就包含了后面要介紹的“時間信息”:起始時間,已執行時間,超時時間,以及是否是 kill 狀態等。相關成員和接口如下圖所示:

其中 checkForInterrupt() 接口的作用就是檢測請求是否應該終止,需滿足以下 3 個條件之一:

1.實例處于 shutdown 狀態;

2.用戶使用 killOp 命令,調用 markKilled() 接口,將 OperationContext 標記為了終止狀態;

3.用戶通過 maxTimeMS 參數給 OperationContext 配置了超時 Deadline,然后檢測到 hasDeadlineExpired() 為 true;

一個請求在執行過程中會多次調用 checkForInterrupt() 檢測自己是否超時,比如在獲取Global ticket,獲取資源鎖,yield,內部迭代重試等階段會主動檢測并超時退出。

備注1:原生 MongoDB 在 3.7.3 版本通過?SERVER-33473 (https://jira.mongodb.org/browse/SERVER-33473)才支持獲取 Global Ticket 時能夠主動超時和打斷,因此更低版本在 qr/qw 較大,請求排隊比較嚴重時無法及時超時退出;而且在 3.7.3 版本通過?SERVER-32638? (https://jira.mongodb.org/browse/SERVER-32638)才支持獲取資源鎖時主動超時,因此更低版本在獲取互斥鎖卡住時也無法及時超時退出。

因此,為了有更好的體驗,強烈建議升級到 4.0 或更高版本。

備注2:終止OperationContext 和 kill 進程/線程行為不同。OperationContext 自己檢測和主動退出的機制使得 killOp 和 maxTimeMS 不會絕對精確。從我們對 maxTimeMS 的測試來看,能夠保證誤差在 1 秒內,大部分在 10ms 級別。也就是說用戶設置的 100ms 超時,在后臺可能會執行 110ms 左右。

使用小貼士:

以常見的 CRUD 操作為例,用戶在命令參數中加上 maxTimeMS 的設置即可。

例如將以下操作的服務端超時設置為 100ms:

// 查詢操作 db.runCommand({find:"cmongo_test", filter:{a:1} , maxTimeMS: 100}) // 插入操作 db.runCommand({insert:"cmongo_test", documents: [{a:1}], maxTimeMS: 100}) // 更新操作 db.runCommand({update:"cmongo_test", updates:[{q:{a:1}, u:{$set:{b:3}}}], maxTimeMS: 100}) // 刪除操作 db.runCommand({delete:"cmongo_test3", deletes: [{q : {a :1}, limit:1}], maxTimeMS: 100})

如果服務端超時,客戶端會收到類似如下的錯誤(客戶端還沒超時斷開的情況下):

{"ok" : 0,"errmsg" : "Encountered non-retryable error during query :: caused by :: operation exceeded time limit","code" : 50,"codeName" : "MaxTimeMSExpired", }

MongoDB 原生版本問題

在騰訊云MongoDB運營過程中,發現原生版本有 2 個比較大的使用痛點:一是原生 5.0 以下版本,在分片集群模式下不支持insert/update/delete 寫命令的超時;二是缺乏服務端默認的 maxTimeMS 配置。

1.原生 5.0 以下版本,在分片集群模式下不支持 insert/update/delete 寫命令的超時

在 4.4 及以下版本中,mongos 在接收到寫命令時,會使用 maxTimeMS 設置請求的 OperationContext 超時,然后將寫入的數據拆分成子請求發給 mongod. 但是 mongod 側收到的子請求中已經沒有了 maxTimeMS 參數,因此 mongod 側不會主動超時。

所以用戶在對 mongos 發起一個攜帶 maxTimeMS 的寫命令時,遲遲等不到超時報錯。

以 4.0 版本為例,常用命令對 maxTimeMS 的支持情況如下:

命令

mongos

mongod

備注

find

支持? ?

支持

https://docs.mongodb.com/v4.0/reference/command/find/

getmore

支持

支持

https://docs.mongodb.com/v4.0/reference/command/getMore/

getMore 這里特指 awaitDataTimeOut 超時,即 cursor 等待有新數據的時間。?SERVER-34277 (https://jira.mongodb.org/browse/SERVER-34277)提議引入新字段進行區分,不過社區還沒有做

findAndModify

支持

支持

https://docs.mongodb.com/v4.0/reference/command/findAndModify/

aggregate相關

aggregate/count/distinct

支持

支持

https://docs.mongodb.com/v4.0/reference/command/aggregate/

https://docs.mongodb.com/v4.0/reference/command/count/

https://docs.mongodb.com/v4.0/reference/command/distinct/

insert

? ×

支持

https://docs.mongodb.com/v4.0/reference/command/insert/

update

? ×

支持

https://docs.mongodb.com/v4.0/reference/command/update/

delete

? ×

支持

https://docs.mongodb.com/v4.0/reference/command/delete/

這個 Bug 直到 4.7.0 版本通過 SERVER-46187 (https://jira.mongodb.org/browse/SERVER-46187)才修復,并隨著今年 5.0 版本的推出才解決。但是,5.0 新版本嘗鮮的寥寥無幾,絕大部分用戶都在使用比較成熟的 4.0 / 4.2 / 4.4 版本。

2.缺乏服務端默認的 maxTimeMS 配置

MongoDB 的命令和參數眾多,普通用戶很難注意并理解 maxTimeMS 的配置,即使想開啟這個功能也需要修改代碼并上線發布。而且如果多租戶共享一個集群,怎么保證其他人也開啟了默認超時也是一個問題。因此,整體使用體驗上需要改進。

另外,和 maxTimeMS 參數對比,原生MongoDB 允許在服務端配置默認的 writeConcern 級別,并在最新發布的 5.0 版本中將默認設置調整為 majority ,防止新手用戶不理解規則導致重要數據出現安全性問題。本質上來說,是通過服務端默認配置來降低用戶的使用成本。

因此,騰訊云MongoDB作為一個注重用戶體驗的云數據庫,認為有必要在服務端支持默認的 maxTimeMS 配置。

騰訊云MongoDB對 maxTimeMS 服務端超時的優化

1.完善 mongos 寫命令對 maxTimeMS 的支持

Mongos 會根據原始請求按目標 shard 分組之后重構子請求,并將每個子請求轉發給對應的 shard。

下圖展示一個寫請求在mongos 上的執行路徑,比較關鍵的點有:

  • 在 runCommand 函數中,會從命令中解析 maxTimeMS(客戶指定的),并設置 OperationContext 的 deadline;

  • 在BatchWriteExec::executeBatch 函數中,會重構子請求,加上 sessionId 和 transactionId 等信息,但是沒有攜帶 maxTimeMS 信息;

  • 這時會出現 2 個問題:

  • OperationContext 只能跟蹤 1 個請求在 1 個進程中的執行信息,也就是說 mongos 和 mongod 各自有自己獨立的 OperationContext。因此,雖然請求在 mongos 中有 deadline,但是 mongod 上沒有;

  • 子請求沒有將 maxTimeMS 透傳給 mongod,因此 mongod 側也無法根據子請求信息設置 OperationContext 的 deadline;

  • 解決方法:在生成子請求時,計算總請求當前還剩余多少執行時間,并作為 maxTimeMS 參數增加到子請求中,再透傳給 mongod。

    整體架構如下所示:

    備注:社區 5.0 版本 SERVER-46187 (https://jira.mongodb.org/browse/SERVER-46187)的修復思路和騰訊云MongoDB的修復方法類似。

    2.支持騰訊云MongoDB服務端默認配置

    騰訊云MongoDB支持分片和副本集 2 種使用模式。

    對于分片集群,可以通過 mongos 在 configSvr 的 config.cmongo_settings 中配置默認參數。mongos 在處理請求時,如果請求中攜帶了用戶指定的 maxTimeMS 參數,則以用戶指定的為準;如果用戶沒有指定,則增加默認配置。

    整體架構如下圖所示:

    對于副本集集群,也是在副本集的 config.cmongo_settings 表中存儲默認配置,如下圖所示:

    備注:默認配置只對用戶請求生效,騰訊云MongoDB集群內部的行為。(比如主從同步,session 上下文信息持久化等請求不受影響)

    使用小貼士

    騰訊云MongoDB在 4.0 和 4.2 版本進行了上述優化。

    對于需要使用 maxTimeMS 功能的用戶,建議先將騰訊云MongoDB的小版本升級到最新,然后通過如下方式進行默認配置:

  • 分片集群登陸 mongos, 副本集登陸 mongod;

  • 配置 config.cmongo_settings 表(在 1 個 mongos 或者 mongod 節點上配置即可,其他 mongos 或者 mongod 節點會在 10 秒內自動同步配置);

  • # 切換到 config DB use config # 第 1 次配置 db.cmongo_settings.insert({"_id" : "maxTimeMS", "value": 1000}) # 配置變更 db.cmongo_settings.update({"_id" : "maxTimeMS"} , {$set: {"value": 2000}}) # 關閉配置 db.cmongo_settings.update({"_id" : "maxTimeMS"} , {$set: {"value": 0}}

    總結

    本文通過對 MongoDB 服務端超時原理和原生版本存在的問題做了分析闡述。騰訊云MongoDB在原生版本的基礎上,解決了 4.0 和 4.2 版本無法在 mongos 側正確處理寫命令超時的問題,并支持了服務端的默認配置,保證服務端超時后能很快退出,防止后端請求積壓導致服務雪崩,最終在功能正確性和用戶體驗上實現了相關優化目標。

    招賢納士

    騰訊云MongoDB作為一款基于開源社區MongoDB版本的文檔數據庫產品,其承載著公司內外包括微信、看點、QQ音樂在內的億級用戶重量級APP產品。

    歡迎有志向從事NoSQL數據庫系統研發的同學加入騰訊TEG云架平NoSQL內核團隊,可通過郵箱(tencentarchitect@126.com)聯系,或者掃碼加入我們的微信群進行技術交流。

    鵝廠架構師圈

    關于我們


    本期出品:騰訊TEG云架平NoSQL內核團隊

    責任編輯:zhenyi/melissa/cathy

    技術分享:關注微信公眾號 【鵝廠架構師】

    總結

    以上是生活随笔為你收集整理的巧用 maxTimeMS 服务端超时,避免承载亿级用户的腾讯云数据库MongoDB服务雪崩的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。