<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          叮咚買菜自建MongoDB上騰訊云實(shí)踐

          共 13425字,需瀏覽 27分鐘

           ·

          2021-12-16 10:09

          隨著近年來公有云技術(shù)及云基礎(chǔ)設(shè)施的發(fā)展,越來越多的企業(yè)轉(zhuǎn)為使用公有云來托管自己的服務(wù)。云數(shù)據(jù)庫因?yàn)閿?shù)據(jù)可靠性、資源彈性、運(yùn)維便捷行,云上數(shù)據(jù)庫服務(wù)也正成為企業(yè)數(shù)據(jù)管理的較好的選擇。??


          本文以叮咚買菜自建MongoDB數(shù)據(jù)庫整體遷移上騰訊云MongoDB為背景,分享叮咚買菜上云過程中的遇到的疑難問題及對應(yīng)的性能優(yōu)化解決方法等,主要包括以下分享內(nèi)容:

          ? ?·?云上MongoDB版本選型

          ? ?·?安全上云及切換方案

          ? ?·?叮咚買菜業(yè)務(wù)側(cè)性能優(yōu)化

          ? ?·?上云遇到的疑難問題及解決方法

          ? ?·?自建上云收益



          叮咚買菜自建

          MongoDB上云背景


          叮咚買菜業(yè)務(wù)以生鮮即時配送為核心,兼?zhèn)湫铝闶垭娚毯蜕r供應(yīng)鏈的特點(diǎn),對高并發(fā)和數(shù)據(jù)一致性有硬性要求。在快速擴(kuò)張的過程中,很多服務(wù)技術(shù)選型以MongoDB作為其主要數(shù)據(jù)存儲。相比其他非即時業(yè)務(wù)場景,叮咚買菜對數(shù)據(jù)庫訪問時延、穩(wěn)定性、數(shù)據(jù)一致性、數(shù)據(jù)安全性也有更苛刻的要求


          借助騰訊云MongoDB產(chǎn)品完善的自動化運(yùn)維、數(shù)據(jù)安全備份回檔、云彈性等能力,可以快速補(bǔ)齊叮咚買菜的核心MongoDB數(shù)據(jù)庫基礎(chǔ)技術(shù)能力,確保數(shù)據(jù)團(tuán)隊(duì)可以游刃有余的支撐業(yè)務(wù)開發(fā)。


          叮咚數(shù)據(jù)團(tuán)隊(duì)基于自建成本、物理資源不足等原因,經(jīng)過綜合評估,決定把MongoDB數(shù)據(jù)遷移到騰訊云MongoDB上。



          云上版本推薦及切換方案


          業(yè)務(wù)正式開始遷移前,結(jié)合叮咚DBA和業(yè)務(wù)同學(xué)了解具體場景、MongoDB集群部署方式、業(yè)務(wù)MongoDB用法、內(nèi)核版本、客戶端版本、客戶端driver類型等。提前了解到用戶第一手信息:

          ? ?·?自建MongoDB版本較低

          ? ?·?客戶端driver主要包括java和PHP

          ? ?·?集群部署都帶tag

          ? ?·?集群存在較頻繁的抖動問題


          2.1. 騰訊云MongoDB內(nèi)核版本推薦

          叮咚自建MongoDB因歷史原因一致保持在官方MongoDB-3.2版本,在一些場景存在性能瓶頸,例如用戶主從讀寫分離時候會遇到讀超時等問題。考慮到用戶對性能要求較高,同時結(jié)合以下技術(shù)點(diǎn),最終推薦用戶使用騰訊云MongoDB-4.0版本,主要原因如下:


          ·?非阻塞從節(jié)點(diǎn)讀(叮咚買菜遇到的低版本主要問題)

          MongoDB-4.x開始,引入了非阻塞的從節(jié)點(diǎn)讀(Non-Blocking Secondary Reads),徹底解決了3.x版本從節(jié)點(diǎn)批量重放oplog時候加全局ParallelBatchWriterMode類型MODE_X鎖引起的讀從節(jié)點(diǎn)讀阻塞問題。


          ·?存儲引擎優(yōu)化(低版本的主要問題)

          相比3.2版本,4.0對存儲引擎做了很多優(yōu)化,例如cache臟數(shù)據(jù)淘汰、鎖粒度、更全的引擎參數(shù)調(diào)整支持等,極大的解決了低版本后臺加索引、大流量讀寫等引起的客戶端訪問阻塞問題。


          ·?更好的寫性能

          相比3.2版本,除了上面提到的非阻塞從節(jié)點(diǎn)讀引起的讀性能提升外,在寫性能方面4.0也更有優(yōu)勢。


          ·?更多有用新功能

          經(jīng)過幾個大版本迭代,4.0版本相比3.2新增了非常多有用功能,例如Retryable Writes(可重試寫)、Change Streams(變更流操作)、Tunable Consistency(更強(qiáng)的可調(diào)一致性)、Schema Validation(模式檢查)、安全功能增強(qiáng)、事務(wù)支持、更豐富的操作類型等。


          ·?分片模式集群擴(kuò)容balance效率更高

          4.0版本相比3.2版本,增加分片擴(kuò)容后的數(shù)據(jù)遷移采用更好的并發(fā)遷移策略,擴(kuò)容數(shù)據(jù)遷移速率更高。


          ·?為何不選擇更高的MongoDB版本?

          MongoDB版本越高功能越多,例如更高版本支持分布式事務(wù)、多字段hash片建支持等。由于叮咚主要是副本集集群,并且對這些新功能需求不強(qiáng)烈,同時綜合集群穩(wěn)定性考慮,最終選擇4.0版本。


          ·?客戶端driver版本兼容性,減少用戶客戶端改造成本

          由于內(nèi)核版本較低,如果升級到高版本,首先需要考慮對應(yīng)客戶端driver版本是否兼容低版本driver。如果客戶端版本和內(nèi)核不兼容,則需要進(jìn)行driver升級甚至代碼改造,因此客戶端driver兼容性也是MongoDB內(nèi)核版本選擇的一個關(guān)鍵指標(biāo)。叮咚技術(shù)團(tuán)隊(duì)經(jīng)過驗(yàn)證,確認(rèn)客戶端版本完全兼容4.0內(nèi)核,代碼無需任何改造。


          常用客戶端driver與MongoDb內(nèi)核版本兼容性詳見:
          Driver類型
          官方兼容性說明
          Java
          https://docs.mongodb.com/drivers/java/sync/v4.3/compatibility/
          golang
          https://docs.mongodb.com/drivers/go/current/compatibility/
          php
          https://docs.mongodb.com/drivers/php/
          其他
          https://docs.mongodb.com/drivers/


          2.2. 安全上云遷移方案

          叮咚自建MongoDB集群包含部分重要數(shù)據(jù),務(wù)必保證遷移的數(shù)據(jù)一致性。常用通用遷移方案如下:


          ·?通用遷移方案


          步驟1:騰訊云DTS for MongoDb全量+增量方式實(shí)時同步自建數(shù)據(jù)到云上MongoDB

          步驟2:選擇凌晨業(yè)務(wù)低峰期判斷DTS延遲進(jìn)度,延遲追上后,業(yè)務(wù)停寫

          步驟3:確保源集群最后一條oplog同步到目標(biāo)集群,客戶端IP地址切到目標(biāo)集群

          通過上面的操作步驟,最終完成不同版本的MongoDB上云。但是,該上云方案有個風(fēng)險(xiǎn),假設(shè)業(yè)務(wù)切換到目標(biāo)新集群后部分讀寫有問題,這時候就需要回滾到源自建集群。由于切換到新集群過程后,可能部分寫流量到了目標(biāo)集群,這時候目標(biāo)集群相比源集群就會有更多的數(shù)據(jù)。這時候,切回到源集群后,也存在數(shù)據(jù)不一致的情況,即使把目標(biāo)集群增量oplog回寫到源集群,也可能存在亂序?qū)懭胍鸬臄?shù)據(jù)混亂問題。


          ·?優(yōu)化方案

          為了解決極端情況下回滾引起的數(shù)據(jù)丟失、數(shù)據(jù)混亂、數(shù)據(jù)不一致等問題,叮咚業(yè)務(wù)集群采用如下更加安全可回滾切割方案:



          當(dāng)業(yè)務(wù)流量從源叮咚自建MongoDB-3.2集群切換到騰訊云MongoDB-4.0后,如果存在版本兼容、業(yè)務(wù)訪問異常等問題,則可直接回滾到騰訊云MongoDB-3.2版本,由于回滾集群和源自建集群版本一致,并且通過DTS實(shí)時同步,因此,可以一定程度保證回滾流程數(shù)據(jù)不混亂、不沖突、不丟失,也可保證切割出問題時候的快速回滾。


          由于叮咚業(yè)務(wù)MongoDB存儲了部分重要數(shù)據(jù),不允許數(shù)據(jù)丟失及混亂,對數(shù)據(jù)一致性要求極高。當(dāng)前方案在切換過程中,仍存在向前回滾時數(shù)據(jù)延遲、連接串更換后應(yīng)用寫錯等風(fēng)險(xiǎn)。因此為了確保實(shí)時同步及回滾數(shù)據(jù)一致性萬無一失,除了DTS的回滾方案,叮咚在業(yè)務(wù)側(cè)增加了幾層保護(hù):通過訂閱和掃描,針對核心庫的數(shù)據(jù)進(jìn)行校驗(yàn);通過流量檢測進(jìn)行業(yè)務(wù)反查;如果出現(xiàn)業(yè)務(wù)數(shù)據(jù)不一致,可以通過工具進(jìn)行可灰度、可控速的方式進(jìn)行補(bǔ)齊。



          叮咚自建MongoDb上云遇到問題及優(yōu)化解決方法


          叮咚不同業(yè)務(wù)從3.2版本上云升級到4.0版本過程中,遇到了一些性能瓶頸問題,主要包括以下問題:

          ? ?·?騰訊云MongoDb短鏈接性能優(yōu)化

          ? ?·?叮咚業(yè)務(wù)側(cè)短鏈接優(yōu)化

          ? ?·?Session定期刷新引起的集群抖動問題


          3.1.短鏈接性能優(yōu)化解決方法

          以叮咚集群其中某業(yè)務(wù)為例,該業(yè)務(wù)部分接口使用PHP driver,因此會涉及到大量的MongoDB短鏈接訪問,以下分別說明叮咚自建集群短鏈接瓶頸優(yōu)化及騰訊云MongoDB短鏈接優(yōu)化過程。


          3.1.1. PHP業(yè)務(wù)短鏈接瓶頸原因

          PHP一次請求訪問,需要如下交互過程日志如下:

          1.?2021-1104T12:45:36.621+0800?I?NETWORK??[conn6]?received?client?metadata?from?…??

          2.?2021-11-04T12:45:36.621+0800?I?COMMAND??[conn6]?command?admin.$cmd?command:?isMaster?…??

          3.?2021-11-04T12:45:36.622+0800?I?COMMAND??[conn6]?command?adminxx.users?command:?saslStart??…

          4.?2021-11-04T12:45:36.626+0800?I?COMMAND??[conn6]?command?admin.$cmd?command:?saslContinue??…

          5.?2021-11-04T12:45:36.627+0800?I?ACCESS???[conn6]?Successfully?authenticated?as?principal??…?

          6.?2021-11-04T12:45:36.627+0800?I?COMMAND??[conn6]?command?adminxx.users?command:?saslContinue

          7.?2021-11-04T12:45:36.627+0800?I?COMMAND??[conn6]?command?admin.$cmd?command:?ping …????

          8.?2021-11-04T12:45:36.627+0800?I?COMMAND??[conn6]?command?x.test??command:?find?{?find:?"test"??

          9.?2021-11-04T12:45:37.636+0800?I?NETWORK??[conn6]?end?connection?…??


          從上面的簡化日志可以看出,一次find請求預(yù)計(jì)需要下面多個操作步驟,并且多次才能完成,主要流程如下:

          ? ?·?TCP三次握手鏈接

          ? ?·?客戶端發(fā)送isMaster命令給服務(wù)端獲取所連節(jié)點(diǎn)

          ? ? ? 的一些狀態(tài)信息、協(xié)議兼容信息

          ? ?·?進(jìn)行sasl多次認(rèn)證交互

          ? ?·?Ping探測獲取往返時延

          ? ?·?真正的業(yè)務(wù)訪問,例如這里的find查詢請求

          ? ?·?四次揮手關(guān)閉本次鏈接對應(yīng)請求


          上面的流程體現(xiàn)出一次訪問,不僅僅建鏈、斷鏈開銷、還有多次認(rèn)證交互以及其他額外交互開銷,最終有效訪問只占用極少一部分開銷,無效訪問浪費(fèi)了系統(tǒng)大部分開銷。此外,PHP業(yè)務(wù)單次訪問的總時延增加,單次訪問總時延如下:

          PHP單次訪問時延=建鏈時間+isMaster()交互時間+認(rèn)證時間+ping時間+數(shù)據(jù)訪問時間

          ?

          3.1.2.叮咚自建MongoDB集群短鏈接部署優(yōu)化

          該用戶集群雖然數(shù)據(jù)量不是很大,但是流量較高,讀寫總流量數(shù)萬/秒,如果直接采用普通副本集模式集群,則存在MongoDB存儲節(jié)點(diǎn)因?yàn)槎替溄恿髁扛咭鸬呢?fù)載問題。叮咚自建MongoDB為了解決短鏈接訪問引起的瓶頸問題,采用如下架構(gòu):



          上圖為某業(yè)務(wù)集群,業(yè)務(wù)讀寫流量較高,總流量數(shù)萬/S,其中有一部分PHP業(yè)務(wù)。考慮到PHP業(yè)務(wù)短鏈接每次訪問需要多次認(rèn)證交互,會增加mongo內(nèi)核壓力,因此用戶采用分片架構(gòu)集群部署,單個分片。客戶端程序和mongos部署在同一臺服務(wù)器,每個客戶端通過本地mongodb:///var/run/mongodb-order.sock/訪問,通過該架構(gòu)來解決短鏈接帶來的性能瓶頸。


          3.1.3.騰訊云MongoDB部署架構(gòu)及優(yōu)化過程

          ·?MongoDB部署架構(gòu)

          騰訊云MongoDB采用叮咚類似架構(gòu),唯一區(qū)別是mongos代理叮咚部署在客戶端機(jī)器本地部署,MongoDB則是獨(dú)立部署,云上MongoDB部署架構(gòu)如下:


          ·?MongoDB短鏈接優(yōu)化

          在業(yè)務(wù)正式上線前,MongoDB團(tuán)隊(duì)對PHP短鏈接進(jìn)行了提前的摸底測試(后端分片無瓶頸,壓一個mongos),測試結(jié)果存在如下現(xiàn)象:

          ?? ·?服務(wù)器CPU空閑

          ? ?·?listener線程CPU消耗較高

          ? ?·?短鏈接并發(fā)越高鏈接報(bào)錯比例越高。

          ? ?·?后端分片MongoDB無瓶頸


          通過分析,netstat查看發(fā)現(xiàn)大量的SYN_RECV 、FIN_WAIT狀態(tài)的鏈接,同時客戶端大量鏈接報(bào)錯,說明mongos代理處理鏈接不及時,這和MongoDB內(nèi)核網(wǎng)絡(luò)線程模型有較大的關(guān)系,MongoDB所有客戶端請求由listener線程進(jìn)行accept處理,accept獲取到一個新鏈接,則創(chuàng)建一個線程,該線程負(fù)責(zé)該鏈接以后的所有數(shù)據(jù)讀寫。


          一個mongos進(jìn)程只有一個listener線程,當(dāng)客戶端鏈接并發(fā)較高的時候,很容易造成鏈接排隊(duì),最終造成客戶端鏈接超時。不過,該瓶頸可以通過部署多個mongos來解決,多個mongos就會有多個listener線程,accept處理能力就會增強(qiáng)。


          最終,綜合成本及性能考慮,選擇多個最低規(guī)格(2PU/4G)的mongos來解決短鏈接瓶頸。


          除了多mongos部署外,還對MongoDB內(nèi)核listen backlog隊(duì)列長度進(jìn)行了適當(dāng)?shù)恼{(diào)整,緩解隊(duì)列滿引起的客戶端鏈接異常問題。



          net.listenBacklog配置在3.6版本開始支持,調(diào)研了常用服務(wù)端中間件nginx、redis,這類中間件都支持listen backlog配置,默認(rèn)取值分別如下:

          ???· Nginx默認(rèn)取值:511

          ???· Redis默認(rèn)取值:511

          ???· MongoDB默認(rèn)取值:SOMAXCONN


          SOMAXCONN也就是操作系統(tǒng)/proc/sys/net/core/somaxcon文件中的值,線上默認(rèn)取值128。修改somaxcon為10240,配置net.listenBacklog為511,保持和nginx、redis推薦默認(rèn)值511 一致。通過測試,net.listenBacklog調(diào)整后,4C規(guī)格測試,短鏈接異常超時現(xiàn)象會有較大緩解。


          listenBacklog配置

          測試結(jié)果

          128

          2000并發(fā)約10%左右請求鏈接報(bào)錯

          511

          2000并發(fā)無任何鏈接報(bào)錯


          3.2.?Session定期刷新業(yè)務(wù)抖動優(yōu)化解決過程


          3.2升級到4.0版本上云過程中,除了用戶短鏈接PHP瓶頸外,另外一個就是session會話定期刷新引起的業(yè)務(wù)抖動問題。


          3.2.1.業(yè)務(wù)抖動現(xiàn)象

          用戶從3.2版本升級到騰訊云4.0版本后,騰訊云MongoDB集群流量監(jiān)控圖如下:

          ?

          如上圖所示,整個現(xiàn)象如下:

          ? ?·?update周期性流量尖刺,尖刺周期5分鐘

          ? ?·?delete周期性流量尖刺,尖刺周期30分鐘

          ? ?·?流量尖刺過程中,時延也對應(yīng)增加,周期性抖動

          ? ?·?CPU周期性消耗


          3.2.2.線下模擬測試

          當(dāng)客戶端眾多,連接數(shù)過高的情況下,副本集主節(jié)點(diǎn)有瞬間大量update甚至delete操作,mongostat和mongotop監(jiān)控如下(測試條件:500并發(fā)短鏈+500并發(fā)長鏈接,進(jìn)行insert持續(xù)性寫入測試):


          ·?mongostat監(jiān)控發(fā)現(xiàn)大量未知update操作,甚至遠(yuǎn)超過正常insert流量



          從上面可以看出,存在大量update更新操作,同時該操作類型統(tǒng)計(jì)甚至超過正常的insert寫入。


          ·?mongotop確定流量來自于哪一個表

          500并發(fā)短鏈接及500并發(fā)長鏈接同時進(jìn)行持續(xù)性insert寫入測試,發(fā)現(xiàn)mongostat監(jiān)控中存在大量的update更新操作,而我們的測試中沒有進(jìn)行update更新操作,于是通過mongotop獲取update操作來源,監(jiān)控結(jié)果入下圖所示:



          從上圖可以看出,大量的update操作來自于config庫的system.sessions表,這是一個潛在隱患。


          ·?其他潛在隱患(system.sessions表集中過期)

          system.sessions表默認(rèn)30分鐘過期,由于session會話數(shù)據(jù)都是集中刷新到system.sessions表,因此該表還存在集中過期的情況,集中過期將讓update定期更新和過期操作疊加,進(jìn)一步加重集群抖動。


          3.2.3.Session模塊內(nèi)核實(shí)現(xiàn)

          從MongoDB-3.6版本開始,MongoDB開始逐步支持單文檔事務(wù),從而開始引入session邏輯會話模塊。不論是副本集mongod還是分片集群的mongos,都會啟動一個定時器刷新cache中緩存的session信息到config庫的system.session表中。


          通過走讀MongoDB內(nèi)核代碼,確定該問題是對system.sessions表做更新引起,內(nèi)核對應(yīng)主要代碼實(shí)現(xiàn)由LogicalSessionCache模塊負(fù)責(zé)session會話管理操作。下面通過一次完整的客戶端訪問為例,分析session模塊核心原理及主要代碼實(shí)現(xiàn):

          ·?步驟1:客戶端發(fā)送isMaster命令到服務(wù)端,服務(wù)端通知客戶端是否支持session管理


          客戶端通過發(fā)送isMaster命令給服務(wù)端,如果服務(wù)端支持session會話管理模塊,則返回session會話超時時間信息給客戶端。


          ·?步驟2:客戶端請求攜帶”lsid”信息發(fā)送給服務(wù)端


          服務(wù)端收到客戶端”lsid”信息后,檢查本地cache是否有該session 信息,如果本地cache沒有該session信息則添加到本地。一個”lsid”代表一個session會話信息。


          如果業(yè)務(wù)沒有創(chuàng)建session信息,則默認(rèn)對一個鏈接創(chuàng)建一個會話信息,鏈接和session一一對應(yīng)。


          ·?步驟三:啟動定時器,定期把cache中的session信息system.sessions表中

          Mongos和mongod實(shí)例都會啟動一個后臺線程,定期把cache中的所有sessions信息同步到config庫的system.sessions表中。同步的session會話信息可以分為以下兩類:

          1.activeSessions活躍session

          activeSessions會話信息主要包括一個定時器周期活躍的session信息(一個定時器周期該session對應(yīng)的客戶端有訪問mongodb)和新創(chuàng)建的session會話信息。


          Mongos或者mongod會定期把a(bǔ)ctiveSessions信息一條一條一次性update到副本集對應(yīng)system.sessions表中。


          2.endSessions會話信息

          endsessions會話信息主要包括客戶端顯示通過endSession命令結(jié)束的會話信息和空閑時間超過system.sessions表對應(yīng)TTL過期時間的會話信息。


          客戶端主動觸發(fā)endSession的session會話信息,mongos也是在同一個定時器中通過remove操作system.sessions表,從而實(shí)現(xiàn)cache和system.sessions表的一致性。Remove操作和活躍session的update操作在同一個定時器完成,update更新完畢后,立馬進(jìn)行remove操作。


          如果是短鏈接,并且關(guān)閉鏈接前主動進(jìn)行了endSession結(jié)束會話操作,副本集可能還存在system.sessions表大量remove的操作。


          如果session長時間空閑,則通過system.sessions表的TTL索引來觸發(fā)本地cache的清理工作。


          ·?定時器相關(guān)

          定時器默認(rèn)定時時間5分鐘,可以通過logicalSessionRefreshMillis配置。


          ·?System.sessions表TTL過期時間

          默認(rèn)30分鐘過期。


          ·?會話統(tǒng)計(jì)信息

          會話統(tǒng)計(jì)信息通過

          “db.serverStatus().logicalSessionRecordCache”命令獲取,如下圖所示:



          logicalSessionRecordCache統(tǒng)計(jì)中,可以分為兩類:session類統(tǒng)計(jì)和transaction事務(wù)類統(tǒng)計(jì),核心統(tǒng)計(jì)項(xiàng)功能說明如下:


          統(tǒng)計(jì)類型

          統(tǒng)計(jì)項(xiàng)

          統(tǒng)計(jì)內(nèi)容說明

          ?

          ?

          Session統(tǒng)計(jì)

          ?

          ?

          activeSessionsCount

          當(dāng)前活躍會話數(shù)

          lastSessionsCollectionJobEntriesRefreshed

          上一個周期刷新到system.session表的活躍會話數(shù)

          lastSessionsCollectionJobEntriesEnded

          上一個周期刷新到system.session表的endSessions會話數(shù)

          lastSessionsCollectionJobCursorsClosed

          上一個周期內(nèi)清理的

          Transaction統(tǒng)計(jì)

          lastTransactionReaperJobEntriesCleanedUp

          本周期內(nèi)清理的transactions表數(shù)據(jù)條數(shù)


          3.2.4. Session問題MongoDB內(nèi)核優(yōu)化解決

          從上面的原理可以看出,業(yè)務(wù)抖動主要因?yàn)閏ache中的session定期集中式刷新,以分片MongoDB集群為例,內(nèi)核層面可以通過以下方式優(yōu)化緩解、也可以通過增加內(nèi)核配置開關(guān)規(guī)避。


          ·?無MongoDB內(nèi)核開發(fā)能力:參數(shù)調(diào)優(yōu)、部署優(yōu)化

          如果沒有MongoDB內(nèi)核開發(fā)能力,可以通過以下方法進(jìn)行session內(nèi)核參數(shù)調(diào)優(yōu)和部署方式調(diào)整來緩解問題:

          方法一:mongos及副本集mongod部署時間打散,避免所有節(jié)點(diǎn)定時器同時生效。

          當(dāng)前集群默認(rèn)啟動后,所有代理和mongod幾乎都是同時啟動的,代理啟動時差較小,session定時器可能同一時間觸發(fā),可以手動打散到不同時間點(diǎn)重啟,包括所有mongos和副本集mongod。


          方法二:短鏈接業(yè)務(wù)考慮定時刷新周期適當(dāng)調(diào)短

          短鏈接默認(rèn)每次請求會生成一個session會話,訪問完畢后不會主動通知MongoDB內(nèi)核釋放session,因此,session在定時周期內(nèi)會大量擠壓,可以考慮縮短定時時間來規(guī)避大量短連接session的定期刷新操作。例如logicalSessionRefreshMillis從默認(rèn)5分鐘調(diào)整為30秒,則集中式的session刷新會散列到多個不同時間點(diǎn)。


          方法三:長鏈接業(yè)務(wù)適當(dāng)調(diào)大定時刷新周期

          實(shí)際測試驗(yàn)證中,默認(rèn)官方driver長鏈接(包括golang、java、c客戶端測試驗(yàn)證)都是一個鏈接對應(yīng)一個session會話id,也就是同一個請求客戶端攜帶的”lsid”保持不變。MongoDB內(nèi)核實(shí)現(xiàn)中,只要每一個鏈接對應(yīng)的定時周期內(nèi)有一次以上活躍請求訪問,則會再次緩存該session id,session id刷新到config.sessions表中后,cache中會清除。


          從上面的長鏈接session cache流程可以看出,一般長鏈接用戶都是連接池配置,總連接數(shù)越高session也會越高。因此長鏈接可以通過以下調(diào)整減少session定期刷新的影響:

          1.?控制連接池最大連接數(shù),減少cache中的session總量

          2.?適當(dāng)調(diào)大logicalSessionRefreshMillis刷新周期,減少頻繁刷新的影響


          ·?內(nèi)核增加禁用session會話功能開關(guān)

          在3.6以下版本,MongoDB是沒有session會話管理模塊的,為了支持事務(wù)和可重試寫功能而引入。


          分析了MongoDB-c-driver客戶端,發(fā)現(xiàn)客戶端第一次報(bào)文交互是否攜帶“l(fā)sid”給服務(wù)端是根據(jù)isMaster的返回內(nèi)容中是否攜帶由” logicalSessionTimeoutMinutes”來決定的,如下:



          實(shí)際上用戶從MongoDB-3.2版本升級到4.0,用戶也不需要事務(wù)、可重試寫功能,客戶端完全沒必要默認(rèn)走session id生成流程。如果客戶端不觸發(fā)session id(也就是報(bào)文交互中的”lsid”),則就不會觸發(fā)mongodb服務(wù)端內(nèi)核啟用session定期刷新功能模塊。因此,可以考慮在MongoDb內(nèi)核代碼實(shí)現(xiàn)中,客戶端isMaster獲取相關(guān)信息的時候,不返回“l(fā)ogicalSessionTimeoutMinutes”信息,這樣客戶端就不會生成”lsid”信息發(fā)送給服務(wù)端。


          4.0官方代碼默認(rèn)寫死,MongoDB內(nèi)核實(shí)現(xiàn)增加session模塊支持開關(guān),如果業(yè)務(wù)沒有事務(wù)等需求,內(nèi)核不應(yīng)答“l(fā)ogicalSessionTimeoutMinutes”信息給客戶端,這樣客戶端認(rèn)為服務(wù)端不支持該功能,就不會主動生成session id交互。


          說明:session會話模塊功能開關(guān)支持,當(dāng)前已驗(yàn)證c driver、java、php,測試驗(yàn)證session問題徹底解決,使用該功能切記對客戶端進(jìn)行提前驗(yàn)證,可能不同客戶端對logicalSessionTimeoutMinutes處理邏輯不一致,特別是使用spring+mongodb整合的客戶端。


          3.2.5.叮咚長鏈接session問題用戶側(cè)優(yōu)化

          叮咚用戶某長鏈接通過騰訊云MongoDB提供的節(jié)點(diǎn)地址自己對集群也做了詳細(xì)的流量監(jiān)控,監(jiān)控曲線如下圖所示:



          在對該長鏈接用戶進(jìn)行MongoDB內(nèi)核優(yōu)化前,可以看出流量周期性尖刺,并且發(fā)現(xiàn)一個歸類:隨著該java長鏈接流量qps越高,定期的sessionupdate尖刺越嚴(yán)重。


          利用線上MongoDB進(jìn)行復(fù)現(xiàn),使用MongoDB官方j(luò)ava driver測試結(jié)果和之前的長鏈接分析一致,也就是一個鏈接一個session會話,也就是java服務(wù)定期最大的session update不會超過總連接數(shù)。但是叮咚用戶的java服務(wù)通過MongoDB內(nèi)核日志,看到如下現(xiàn)象:


          1.?Thu?Sep??2?18:07:19.833?I?COMMAND??[conn48527]?command?xx.xxx?command:?insert?{?insert:?"xx",?ordered:?true,?$db:?"xx",?$clusterTime:?{?clusterTime:?Timestamp(1630577239,?387),?signature:?{?hash:?BinData(0,?B37C8600CE543BEE2D8085730AADD91CB13C14AF),?keyId:?7002593870005403649?}?},?lsid:?{?id:?UUID("3ce872be-5a8d-4a1b-b656-8ba33b3cb15d")?}?}?ninserted:1?keysInserted:2?numYields:0?reslen:230?locks:{?Global:?{?acquireCount:?{?r:?2,?w:?2?}?},?Database:?{?acquireCount:?{?w:?2?}?},?Collection:?{?acquireCount:?{?w:?1?}?},?oplog:?{?acquireCount:?{?w:?1?}?}?}?protocol:op_msg?0ms??


          2.?Thu?Sep??2?18:07:19.921?D?COMMAND??[conn48527]?run?command?xx.$cmd?{?insert:?"xxxx",?ordered:?true,?$db:?"xxx",?$clusterTime:?{?clusterTime:?Timestamp(1630577239,?429),?signature:?{?hash:?BinData(0,?B37C8600CE543BEE2D8085730AADD91CB13C14AF),?keyId:?7002593870005403649?}?},?lsid:?{?id:?UUID("ab3e1cb8-1ba1-4e03-bf48-c388f5fc49d1")?}?}??


          3.?Thu?Sep??2?18:07:19.922?I?COMMAND??[conn48527]?command?xxx.xxx?command:?insert?{?insert:?"oxxx",?ordered:?true,?$db:?"maicai",?$clusterTime:?{?clusterTime:?Timestamp(1630577239,?429),?signature:?{?hash:?BinData(0,?B37C8600CE543BEE2D8085730AADD91CB13C14AF),?keyId:?7002593870005403649?}?},?lsid:?{?id:?UUID("ab3e1cb8-1ba1-4e03-bf48-c388f5fc49d1")?}?}?ninserted:1?keysInserted:2?numYields:0?reslen:230?locks:{?Global:?{?acquireCount:?{?r:?2,?w:?2?}?},?Database:?{?acquireCount:?{?w:?2?}?},?Collection:?{?acquireCount:?{?w:?1?}?},?oplog:?{?acquireCount:?{?w:?1?}?}?}?protocol:op_msg?0ms??


          4.?Thu?Sep??2?18:07:19.765?I?COMMAND??[conn48527]?command?xxx.xxx?command:?find?{?find:?"xxx",?filter:?{?status:?{?$in:?[?1,?2,?4,?5,?9,?11,?13,?3,?7,?15?]?},?order_number:?"xxx",?is_del:?false?},?sort:?{?_id:?-1?},?$db:?"xxx",?$clusterTime:?{?clusterTime:?Timestamp(1630577239,?375),?signature:?{?hash:?BinData(0,?B37C8600CE543BEE2D8085730AADD91CB13C14AF),?keyId:?7002593870005403649?}?},?lsid:?{?id:?UUID("ed1f0fd8-c09c-420a-8a96-10dfe8ddb454")?}?}?planSummary:?IXSCAN?{?order_number:?1?}?keysExamined:8?docsExamined:8?hasSortStage:1?cursorExhausted:1?numYields:0?nreturned:4?reslen:812?locks:{?Global:?{?acquireCount:?{?r:?1?}?},?Database:?{?acquireCount:?{?r:?1?}?},?Collection:?{?acquireCount:?{?r:?1?}?}?}?protocol:op_msg?0ms??


          從上面的日志可以看出,即使是同一個長鏈接上面的多次會話,客戶端也會攜帶多個不同的”lsid”發(fā)送給MongoDB服務(wù)端,因此需要解決為何java服務(wù)同一個鏈接多次訪問會生成多個session id,即”lsid”。


          通過排查客戶端,最終定位問題是客戶端的埋點(diǎn)監(jiān)控在升級到MongoDB-4.0后,觸發(fā)每次請求生成一個新的”lsid”。



          叮咚買菜自建上云

          收益總結(jié)


          自建MongoDB遷移騰訊云MongoDB后,帶來了如下收益:

          ·?通過梳理拆分,把一些核心的復(fù)雜的MongoDB集群,垂直拆分為多個集群,耦合性降低,穩(wěn)定性提高。

          ·?集群穩(wěn)定性提高,上云前業(yè)務(wù)遇到的各種MongoDB訪問毛刺和抖動問題得到了徹底解決。

          ·?騰訊云MongoDB相比自建MongoDB性能更好,并能夠充分利用云的彈性擴(kuò)容能力,不用預(yù)留過多的硬件資源,從而節(jié)省了較大成本。

          ·?騰訊云MongoDB完善的監(jiān)控告警、數(shù)據(jù)備份回檔、跨地域容災(zāi)、實(shí)時巡檢、7x24小時在線服務(wù)等,使得可運(yùn)維性、數(shù)據(jù)安全、故障預(yù)發(fā)現(xiàn)等能力得以增強(qiáng)。

          ·?遷移到騰訊云,也可以利用騰訊云技術(shù)團(tuán)隊(duì)的技術(shù)優(yōu)勢,幫助分析定位解決一些MongoDB深層次的疑難技術(shù)問題。



          作者:叮咚買菜基礎(chǔ)技術(shù)/騰訊云MongoDB
          叮咚買菜技術(shù)團(tuán)隊(duì):
          叮咚買菜基礎(chǔ)技術(shù),支撐叮咚買菜核心業(yè)務(wù)的資源、數(shù)據(jù)、基礎(chǔ)架構(gòu),是一支技術(shù)背景深厚、充滿激情與理想、堅(jiān)持同目標(biāo)共進(jìn)退,打勝仗的團(tuán)隊(duì)。尤其重視技術(shù)人才培養(yǎng)和發(fā)展成長,很多技術(shù)骨干都是內(nèi)部成長發(fā)展起來的。
          騰訊云MongoDB團(tuán)隊(duì):
          騰訊云MongoDB當(dāng)前服務(wù)于游戲、電商、社交、教育、新聞資訊、金融、物聯(lián)網(wǎng)、軟件服務(wù)等多個行業(yè);MongoDB團(tuán)隊(duì)(簡稱CMongo)致力于對開源MongoDb內(nèi)核進(jìn)行深度研究及持續(xù)性優(yōu)化(如百萬庫表、物理備份、免密、審計(jì)等),為用戶提供高性能、低成本、高可用性的安全數(shù)據(jù)庫存儲服務(wù)。后續(xù)持續(xù)分享MongoDb在騰訊內(nèi)部及外部的典型應(yīng)用場景、踩坑案例、性能優(yōu)化、內(nèi)核模塊化分析。

          ?


          -- 更多精彩 --

          億級月活全民K歌Feed業(yè)務(wù)在騰訊云MongoDB中的應(yīng)用及優(yōu)化實(shí)踐


          點(diǎn)擊閱讀原文,了解更多優(yōu)惠

          瀏覽 46
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  秋霞国产午夜精品免费视频 | 免费观看欧美成人网站 | 青草2017男人天堂 | 国产美女被操网站 | 2021高清无码 |