Mongodb特定場景效能數十倍提升優化實踐(記一次mongodb核心叢集雪崩故障)

y123456yzzyz發表於2020-10-18

Mongodb 特定場景效能數十倍提升優化實踐 ( 記一次 mongodb 核心叢集雪崩故障 )

關於作者

前滴滴出行技術專家,現任OPPO 文件資料庫 mongodb 負責人,負責 oppo 千萬級峰值 TPS/ 十萬億級資料量文件資料庫 mongodb 核心研發及運維工作,一直專注於分散式快取、高效能服務端、資料庫、中介軟體等相關研發。 Github 賬號地址 : https://github.com/y123456yz

1. 問題背景

某核心JAVA 長連線服務使用 mongodb 作為主要儲存,客戶端數百臺機器連線同一 mongodb 叢集,短期內出現多次效能抖動問題,此外,還出現一次“雪崩”故障,同時流量瞬間跌零,無法自動恢復。本文分析這兩次故障的根本原因,包括客戶端配置使用不合理、 mongodb 核心連結認證不合理、代理配置不全等一系列問題,最終經過多方努力確定問題根源。

該叢集有十來個業務介面訪問,每個介面部署在數十臺業務伺服器上面,訪問該mongodb 機器的客戶端總數超過數百臺,部分請求一次拉取數十行甚至百餘行資料。

該叢集為2 機房同城多活叢集 ( 選舉節不消耗太多資源,異地的第三機房來部署選舉節點 ) ,架構圖如下:

從上圖可以看出,為了實現多活,在每個機房都部署有對應代理,對應機房客戶端連結對應機房的mongos 代理,每個機房多個代理。代理層部署 IP:PORT 地址列表 ( 注意:不是真實 IP 地址 ) 如下:

A 機房代理地址列表: 1.1.1.1:111,2.2.2.2:1111,3.3.3.3:1111

B 機房代理地址列表: 4.4.4.4:1111,4.4.4.4:2222

A 機房三個代理部署在三臺不同物理機, B 機房 2 個代理部署在同一臺物理機。此外, A 機房和 B 機房為同城機房,跨機房訪問時延可以忽略。

叢集儲存層和config server 都採用同樣的架構: A 機房 (1 主節點 +1 從節點 ) + B 機房 (2 從節點 )+C 機房 (1 個選舉節點 arbiter) ,即 2( 資料節點 )+2( 資料節點 )+1( 選舉節點 ) 模式。

該機房多活架構可以保證任一機房掛了,對另一機房的業務無影響,具體機房多活原理如下:

1.  如果A 機房掛掉,由於代理是無狀態節點, A 機房掛掉不會影響 B 機房的代理。

2.  如果A 機房掛掉,同時主節點在 A 機房,這時候 B 機房的 2 個資料節點和 C 機房的選舉節點一共三個節點,可以保證新選舉需要大於一半以上節點這個條件,於是 B 機房的資料節點會在短時間內選舉出一個新的主節點,這樣整個儲存層訪問不受任何影響。

本文重點分析如下6 個疑問點:

1.  為什麼突發流量業務會抖動?

2.  為什麼資料節點沒有任何慢日誌,但是代理負載缺100%

3.  為何mongos 代理引起數小時的“雪崩”,並且長時間不可恢復?

4.  為何一個機房代理抖動,對應機房業務切到另一個機房後,還是抖動?

5.  為何異常時候抓包分析,客戶端頻繁建鏈斷鏈,並且同一個連結建鏈到斷鏈間隔很短?

6.  理論上代理就是七層轉發,消耗資源更少,相比mongod 儲存應該更快,為何 mongod 儲存節點無任何抖動, mongos 代理缺有抖動?

2. 故障過程

2.1 業務偶爾流量高峰,業務抖動?

該叢集一段時間內有多次短暫的抖動,當A 機房客戶端抖動後,發現 A 機房對應代理負載很高,於是切換 A 機房訪問 B 機房代理,但是切換後 B 機房代理同樣抖動,也就是多活切換沒有作用,具體過程分析如下。

2.1.1 儲存節點慢日誌分析

首先,分析該叢集所有mongod 儲存節點系統 CPU MEM IO load 等監控資訊,發現一切正常,於是分析每個 mongod 節點慢日誌 ( 由於該叢集對時延敏感,因此慢日誌調整為 30ms) ,分析結果如下:

從上圖可以看出,儲存節點在業務抖動的時候沒有任何慢日誌,因此可以判斷儲存節點一切正常,業務抖動和mongod 儲存節點無關。

2.1.2 Mongos 代理分析

儲存節點沒有任何問題,因此開始排查mongos 代理節點。由於歷史原因,該叢集部署在其他平臺,該平臺對 QPS 、時延等監控不是很全,造成早期抖動的時候監控沒有及時發現。抖動後,遷移該平臺叢集到 oppo 自研的新管控平臺,新平臺有詳細的監控資訊,遷移後 QPS 監控曲線如下:

每個流量徒增時間點,對應業務監控都有一波超時或者抖動,如下:


分析對應代理mongos 日誌,發現如下現象:抖動時間點 mongos.log 日誌有大量的建連結和斷連結的過程,如下圖所示:

    從上圖可以看出,一秒鐘內有幾千個連結建立,同時有幾千個連結斷開,此外抓包發現很多連結短期內即斷開連結,現象如下( 斷鏈時間 - 建鏈時間 =51ms, 部分 100 ms 斷開 )

     對應抓包如下:

此外,該機器代理上客戶端連結低峰期都很高,甚至超過正常的QPS 值, QPS 大約 7000-8000 ,但是 conn 連結缺高達 13000 mongostat 獲取到監控資訊如下:


2.1.3 代理機器負載分析

每次突發流量的時候,代理負載很高,通過部署指令碼定期取樣,抖動時間點對應監控圖如下圖所示:

      從上圖可以看出,每次流量高峰的時候CPU 負載都非常的高,而且是 sy% 負載, us% 負載很低,同時 Load 甚至高達好幾百,偶爾甚至過千。

2.1.4 抖動分析總結

   從上面的分析可以看出,某些時間點業務有突發流量引起系統負載很高。 根因真的是因為突發流量嗎?其實不然,請看後續分析,這其實是一個錯誤結論。沒過幾天,同一個叢集雪崩了。

   於是業務梳理突發流量對應介面,梳理出來後下掉了該介面,QPS 監控曲線如下:

為了減少業務抖動,因此下掉了突發流量介面,此後幾個小時業務不再抖動。當下掉突發流量介面後,我們還做了如下幾件事情:

1.  由於沒找到mongos 負載 100% 真正原因,於是每個機房擴容 mongs 代理,保持每個機房 4 個代理,同時保證所有代理在不同伺服器,通過分流來儘量減少代理負載。

2.  通知A 機房和 B 機房的業務配置上所有的 8 個代理,不再是每個機房只配置對應機房的代理 ( 因為第一次業務抖動後,我們分析 mongodb java sdk ,確定 sdk 均衡策略會自動剔除請求時延高的代理,下次如果某個代理再出問題,也會被自動剔除 )

3.  通知業務把所有客戶端超時時間提高到500ms

  但是, 心裡始終有很多疑惑和懸念,主要在以下幾個點:

1.  儲存節點4 個,代理節點 5 個,儲存節點無任何抖動 ,反而七層轉發的代理負載高?

2.  為何抓包發現很多新連線幾十ms 或者一百多 ms 後就斷開連線了?頻繁建鏈斷鏈?

3.  為何代理QPS 只有幾萬,這時代理 CPU 消耗就非常高,而且全是 sy% 系統負載? 以我多年中介軟體代理研發經驗,代理消耗的資源很少才對,而且 CPU 只會消耗 us% ,而不是 sy% 消耗。

2.2 同一個業務幾天後 雪崩   

好景不長,業務下掉突發流量的介面沒過幾天,更嚴重的故障出現了,機房B 的業務流量在某一時刻直接跌 0 了,不是簡單的抖動問題,而是業務直接流量跌 0 ,系統 sy% 負載 100% ,業務幾乎 100% 超時重連。

2.2.1 機器系統監控分析

機器CPU 和系統負載監控如下:

從上圖可以看出,幾乎和前面的突發流量引起的系統負載過高現象一致,業務CPU sy% 負載 100% load 很高。登陸機器獲取 top 資訊,現象和監控一致。

  同一時刻對應網路監控如下:

磁碟IO 監控如下:

從上面的系統監控分析可以看出,出問題的時間段,系統CPU sy% load 負載都很高,網路讀寫流量幾乎跌 0 ,磁碟 IO 一切正常,可以看出整個過程幾乎和之前突發流量引起的抖動問題完全一致。

2.2.2 業務如何恢復

   第一次突發流量引起的抖動問題後,我們擴容所有的代理到8 個,同時通知業務把所有業務介面配置上所有代理。由於業務介面眾多,最終 B 機房的業務沒有配置全部代理,只配置了原先的兩個處於同一臺物理機的代理 (4.4.4.4:1111,4.4.4.4:2222) ,最終觸發 mongodb 的一個效能瓶頸 ( 詳見後面分析 ) ,引起了整個 mongodb 叢集 雪崩

最終,業務通過重啟服務,同時把B 機房的 8 個代理同時配置上,問題得以解決。

2.2.3 mongos 代理例項監控分析

分析該時間段代理日誌,可以看出和2.1 同樣得現象,大量的新鍵連線,同時新連線在幾十 ms 、一百多 ms 後又關閉連線。整個現象和之前分析一致,這裡不在統計分析對應日誌。

此外,分析當時的代理QPS 監控,正常 query 讀請求的 QPS 訪問曲線如下,故障時間段 QPS 幾乎跌零雪崩了:

Command 統計監控曲線如下:

    從上面的統計可以看出,當該代理節點的流量故障時間點有一波尖刺,同時該時間點的command 統計瞬間飆漲到 22000( 實際可能更高,因為我們監控取樣週期 30s, 這裡只是平均值 ) ,也就是瞬間有 2.2 萬個連線瞬間進來了。 Command 統計實際上是 db.ismaster() 統計,客戶端 connect 服務端成功後的第一個報文就是 ismaster 報文,服務端執行 db.ismaster() 後應答客戶端,客戶端收到後開始正式的 sasl 認證流程。

正常客戶端訪問流程如下:

1.  客戶端發起與mongos 的連結

2.  Mongos 服務端 accept 接收連結後,連結建立成功

3.  客戶端傳送db.isMaster() 命令給服務端

4.  服務端應答isMaster 給客戶端

5.  客戶端發起與mongos 代理的 sasl 認證 ( 多次和 mongos 互動 )

6.  客戶端發起正常的find() 流程

客戶端SDK 連結建立成功後傳送 db.isMaster() 給服務端的目的是為了負載均衡策略和判斷節點是什麼型別,保證客戶端快速感知到訪問時延高的代理,從而快速剔除往返時延高的節點,同時確定訪問的節點型別。

此外,通過提前部署的指令碼, 該指令碼在系統負載高的時候自動抓包,從抓包分析結果如下圖所示:

  上圖時序分析如下:

1.   11:21:59.506174 連結建立成功

2.   11:21:59.506254 客戶端傳送 db.IsMaster() 到服務端

3.   11:21:59.656479 客戶端傳送 FIN 斷鏈請求

4.   11:21:59.674717 服務端傳送 db.IsMaster() 應答給客戶端

5.   11:21:59.675480 客戶端直接 RST

   3 和第 1 個報文之間相差大約 150ms ,最後和業務確定該客戶端 IP 對應的超時時間配置,確定就是 150ms 。此外,其他抓包中有類似 40ms 100ms 等超時配置,通過對應客戶端和業務確認,確定對應客戶端業務介面超時時間配置的就是 40ms 100ms 等。因此,結合抓包和客戶端配置,可以確定當代理超過指定超時時間還沒有給客戶端 db.isMaster() 返回值,則客戶端立馬超時,超時後立馬發起重連請求。

 

總結: 通過抓包和mongos 日誌分析,可以確定連結建立後快速斷開的原因是:客戶端訪問代理的第一個請求 db.isMaster() 超時了,因此引起客戶端重連。重連後又開始獲取 db.isMaster() 請求,由於負載 CPU 100%, 很高,每次重連後的請求都會超時。其中配置超時時間為 500ms 的客戶端,由於 db.isMaster() 不會超時,因此後續會走 sasl 認證流程。

       因此可以看出,系統負載高和反覆的建鏈斷鏈有關,某一時刻客戶端大量建立連結(2.2W) 引起負載高,又因為客戶端超時時間配置不一,超時時間配置得比較大得客戶端最終會進入 sasl 流程,從核心態獲取隨機數,引起 sy% 負載高, sy% 負載高又引起客戶端超時,這樣整個訪問過程就成為一個“死迴圈”,最終引起 mongos 代理雪崩。

 

2.3 線下模擬故障

到這裡,我們已經大概確定了問題原因,但是為什麼故障突發時間點那一瞬間2 萬個請求就會引起 sy% 負載 100% 呢,理論上一秒鐘幾萬個連結不會引起如此嚴重的問題,畢竟我們機器有 40 CPU 。因此,分析反覆建鏈斷鏈為何引起系統 sy% 負載 100% 就成為了本故障的關鍵點。

2.3.1 模擬故障過程

   模擬頻繁建鏈斷鏈故障步驟如下:

1.  修改mongos 核心程式碼,所有請求全部延時 600ms

2.  同一臺機器起兩個同樣的mongos ,通過埠區分

3.  客戶端啟用6000 個併發連結,超時時間 500ms

   通過上面的操作,可以保證所有請求超時,超時後客戶端又會立馬開始重新建鏈,再次建鏈後訪問mongodb 還會超時,這樣就模擬了反覆建鏈斷鏈的過程。此外,為了保證和雪崩故障環境一致,把 2 mongos 代理部署在同一臺物理機。

 

2.3.2 故障模擬測試結果

為了保證和故障的mongos 代理硬體環境一致,因此選擇故障同樣型別的伺服器,並且作業系統版本一樣 (2.6.32-642.el6.x86_64) ,程式都跑起來後,問題立馬浮現:

    由於出故障的伺服器作業系統版本linux-2.6 過低,因此懷疑可能和作業系統版本有問題,因此升級同一型別的一臺物理機到 linux-3.10 版本,測試結果如下:

從上圖可以看出,客戶端6000 併發反覆重連,服務端壓力正常,所有 CPU 消耗在 us% sy% 消耗很低。使用者態 CPU 消耗 3 CPU ,核心態 CPU 消耗幾乎為 0 ,這是我們期待的正常結果,因此覺得該問題可能和作業系統版本有問題。

為了驗證更高並反覆建鏈斷鏈在Linux-3.10 核心版本是否有 2.6 版本同樣的 sy% 核心態 CPU 消耗高的問題,因此把併發從 6000 提升到 30000 ,驗證結果如下:

測試結果: 通過修改mongodb 核心版本故意讓客戶端超時反覆建鏈斷鏈,在 linux-2.6 版本中, 1500 以上的併發反覆建鏈斷鏈系統 CPU sy% 100% 的問題即可浮現。但是,在 Linux-3.10 版本中,併發到 10000 後, sy% 負載逐步增加,併發越高 sy% 負載越高。

總結: linux-2.6 系統中, mongodb 只要每秒有幾千的反覆建鏈斷鏈,系統 sy% 負載就會接近 100% Linux-3.10 ,併發 20000 反覆建鏈斷鏈的時候, sy% 負載可以達到 30% ,隨著客戶端併發增加, sy% 負載也相應的增加。 Linux-3.10 版本相比 2.6 版本針對反覆建鏈斷鏈的場景有很大的效能改善,但是不能解決根本問題。

2.4 客戶端反覆建鏈斷鏈引起 sy% 100% 根因

為了分析%sy 系統負載高的原因,安裝 perf 獲取系統 top 資訊,發現所有 CPU 消耗在如下介面:

     perf 分析可以看出, cpu 消耗在 _spin_lock_irqsave 函式,繼續分析核心態呼叫棧,得到如下堆疊資訊:

     - 89.81% 89.81% [kernel] [k] _spin_lock_irqsave ▒
     - _spin_lock_irqsave  ▒
     - mix_pool_bytes_extract ▒
     - extract_buf ▒
     extract_entropy_user ▒
     urandom_read  ▒
     vfs_read ▒
     sys_read ▒
     system_call_fastpath ▒
     0xe82d

上面的堆疊資訊說明,mongodb 在讀取  /dev/urandom ,並且由於多個執行緒同時讀取該檔案,導致消耗在一把 spinlock 上。

到這裡問題進一步明朗了,故障root case 不是每秒幾萬的連線數導致 sys 過高引起。根本原因是每個 mongo 客戶端的新連結會導致 mongodb 後端新建一個執行緒,該執行緒在某種情況下會呼叫 urandom_read 去讀取隨機數 /dev/urandom ,並且由於多個執行緒同時讀取,導致核心態消耗在一把 spinlock 鎖上,出現 cpu 高的現象。

2.5 mongodb 核心隨機數優化

2.5.1 mongodb 核心原始碼定位分析

上面的分析已經確定,問題根源是mongodb 核心多個執行緒讀取 /dev/urandom 隨機數引起,走讀 mongodb 核心程式碼,發現讀取該檔案的地方如下:


上面是生成隨機數的核心程式碼,每次獲取隨機數都會讀取 /dev/urandom 系統檔案,所以只要找到使用該介面的地方即可即可分析出問題。

繼續走讀程式碼,發現主要在如下地方:

// 服務端收到客戶端 sasl 認證的第一個報文後的處理,這裡會生成隨機數

// 如果是 mongos ,這裡就是接收客戶端 sasl 認證的第一個報文的處理流程

Sasl_scramsha1_server_conversation::_firstStep(...) {

    ... ...

    unique_ptr<SecureRandom> sr(SecureRandom::create());

    binaryNonce[0] = sr->nextInt64();

    binaryNonce[1] = sr->nextInt64();

    binaryNonce[2] = sr->nextInt64();

    ... ...

}

//mongos 相比 mongod 儲存節點就是客戶端, mongos 作為客戶端也需要生成隨機數

SaslSCRAMSHA1ClientConversation::_firstStep(...) {

    ... ...

    unique_ptr<SecureRandom> sr(SecureRandom::create());

    binaryNonce[0] = sr->nextInt64();

    binaryNonce[1] = sr->nextInt64();

    binaryNonce[2] = sr->nextInt64();

    ... ...

}

2.5.2 mongodb 核心原始碼隨機數優化

2.5.1 分析可以看出, mongos 處理客戶端新連線 sasl 認證過程都會通過 "/dev/urandom" 生成隨機數,從而引起系統sy% CPU 過高,我們如何優化隨機數演算法就是解決本問題的關鍵。

繼續分析mongodb 核心原始碼,發現使用隨機數的地方很多,其中有部分隨機數通過使用者態演算法生成,因此我們可以採用同樣方法,在使用者態生成隨機數,使用者態隨機數生成核心演算法如下:

    class PseudoRandom {

    ... ...

    uint32_t _x;

    uint32_t _y;

    uint32_t _z;

    uint32_t _w;

}

   該演算法可以保證產生的資料隨機分佈,該演算法原理詳見:

    http://en.wikipedia.org/wiki/Xorshift

   也可以檢視如下git 地址獲取演算法實現:

    mongodb 隨機數生成演算法註釋

   總結: 通過優化sasl 認證的隨機數生成演算法為使用者態演算法後, CPU sy% 100% 的問題得以解決, 同時代理效能在短連結場景下有了數倍/ 數十倍的效能提升

3. 問題總結及疑問解答

從上面的分析可以看出,該故障由多種因素連環觸發引起,包括客戶端配置使用不當、mongodb 服務端核心極端情況異常缺陷、監控不全等。總結如下:

1.  客戶端配置不統一,同一個叢集多個業務介面配置千奇百怪,超時配置、連結配置各不相同,增加了抓包排查故障的難度,超時時間設定太小容易引起反覆重連。

2.  客戶端需要配全所有mongos 代理,這樣當一個代理故障的時候,客戶端 SDK 預設會剔除該故障代理節點,從而可以保證業務影響最小,就不會存在單點問題。

3.  同一叢集多個業務介面應該使用同一配置中心統一配置,避免配置不統一。

4.  Mongodb 核心的新連線隨機演算法存在嚴重缺陷,在極端情況下引起嚴重效能抖動,甚至業務“雪崩”。

分析到這裡,我們可以回答第1 章節的 6 個疑問點了,如下:

為什麼突發流量業務會抖動?

答:由於業務是java 業務,採用連結池方式連結 mongos 代理,當有突發流量的時候,連結池會增加連結數來提升訪問 mongodb 的效能,這時候客戶端就會新增連結,由於客戶端眾多,造成可能瞬間會有大量新連線和 mongos 建鏈。連結建立成功後開始做 sasl 認證,由於認證的第一步需要生成隨機數,就需要訪問作業系統 "/dev/urandom" 檔案。又因為 mongos 代理模型是預設一個連結一個執行緒,所以會造成瞬間多個執行緒訪問該檔案,進而引起核心態 sy% 負載過高。

為何mongos 代理引起“雪崩”,流量為何跌零不可用?

答:原因客戶端某一時刻可能因為流量突然有增加,連結池中連結數不夠用,於是增加和mongos 代理的連結,由於是老叢集,代理還是預設的一個連結一個執行緒模型,這樣瞬間就會有大量連結,每個連結建立成功後,就開始 sasl 認證,認證的第一步服務端需要產生隨機數, mongos 服務端通過讀取 "/dev/urandom" 獲取隨機數,由於多個執行緒同時讀取該檔案觸發核心態spinlock CPU sy% 100% 問題。由於 sy% 系統負載過高,由於客戶端超時時間設定過小,進一步引起客戶端訪問超時,超時後重連,重連後又進入 sasl 認證,又加劇了讀取 "/dev/urandom" 檔案,如此反覆迴圈持續。

此外,第一次業務抖動後,服務端擴容了8 mongos 代理,但是客戶端沒有修改,造成 B 機房業務配置的 2 個代理在同一臺伺服器,無法利用 mongo java sdk 的自動剔除負載高節點這一策略,所以最終造成 雪崩

為什麼資料節點沒有任何慢日誌,但是代理負載卻CPU sy% 100%

答:由於客戶端java 程式直接訪問的是 mongos 代理,所以大量連結只發生在客戶端和 mongos 之間,同時由於客戶端超時時間設定太短 ( 有介面設定位幾十 ms ,有的介面設定位一百多 ms ,有的介面設定位 500ms) ,就造成在流量峰值的時候引起連鎖反應 ( 突發流量系統負載高引起客戶端快速超時,超時後快速重連,進一步引起超時,無限死迴圈 ) Mongos mongod 之間也是連結池模型,但是 mongos 作為客戶端訪問 mongod 儲存節點的超時很長,預設都是秒級別,所以不會引起反覆超時建鏈斷鏈。

為何A 機房代理抖動的時候, A 機房業務切到 B 機房後,還是抖動?

答:當A 機房業務抖動,業務切換到 B 機房的時候,客戶端需要重新和服務端建立連結認證,又會觸發大量反覆建鏈斷鏈和讀取隨機數 "/dev/urandom" 的流程,所以最終造成機房多活失敗。

為何異常時候抓包分析,客戶端頻繁建鏈斷鏈,並且同一個連結建鏈到斷鏈間隔很短?

答:頻繁建鏈斷鏈的根本原因是系統sy% 負載高,客戶端極短時間內建立連結後又埠的原因是客戶端配置超時時間太短。

理論上代理就是七層轉發,消耗資源更少,相比mongod 儲存應該更快,為何 mongod 儲存節點無任何抖動, mongos 代理卻有嚴重抖動?

答:由於採用分片架構,所有mongod 儲存節點前面都有一層 mongos 代理, mongos 代理作為 mongod 儲存節點的客戶端,超時時間預設秒級,不會出現超時現象,也就不會出現頻繁的建鏈斷鏈過程。

如果mongodb 叢集採用普通複製集模式,客戶端頻繁建鏈斷鏈是否可能引起 mongod 儲存節點同樣的 雪崩

   答:會。如果客戶端過多,作業系統核心版本過低,同時超時時間配置過段,直接訪問複製集的mongod 儲存節點,由於客戶端和儲存節點的認證過程和與 mongos 代理的認證過程一樣,所以還是會觸發引起頻繁讀取 "/dev/urandom" 檔案,引起 CPU sy% 負載過高,極端情況下引起雪崩。

4.  雪崩 解決辦法

從上面的一系列分析,問題在於客戶端配置不合理,加上mongodb 核心認證過程讀取隨機數在極端情況下存在缺陷,最終造成雪崩。如果沒有 mongodb 核心研發能力,可以通過規範化客戶端配置來避免該問題。當然,如果客戶端配置規範化,同時 mongodb 核心層面解決極端情況下的隨機數讀取問題,這樣問題可以得到徹底解決。

4.1 JAVA SDK 客戶端配置規範化

在業務介面很多,客戶端機器很多的業務場景,客戶端配置一定要做到如下幾點:

1.  超時時間設定為秒級,避免超時時間設定過端引起反覆的建鏈斷鏈。

2.  客戶端需要配置所有mongos 代理地址,不能配置單點,否則流量到一個 mongos 很容易引起瞬間流量峰值的建鏈認證。

3.  增加mongos 代理數量,這樣可以分流,保證同一時刻每個代理的新鍵連結儘可能的少,客戶端在多代理配置時,預設是均衡流量分發的,如果某個代理負載高,客戶端會自動剔除。

     如果沒有mongodb 核心原始碼研發能力,可以參考該客戶端配置方法,同時淘汰 linux-2.6 版本核心,採用 linux-3.10 或者更高版本核心,基本上可以規避踩同樣型別的坑。

4.2 mongodb 核心原始碼優化 ( 擯棄核心態獲取隨機數,選擇使用者態隨機數演算法 )

   詳見2.5.2 章節。

4.3 PHP 短連結業務,如何規避踩坑

   由於PHP 業務屬於短連結業務,如果流量很高,不可避免的要頻繁建鏈斷鏈,也就會走 sasl 認證流程,最終多執行緒頻繁讀取 "/dev/urandom" 檔案,很容易引起前面的問題。這種情況,可以採用 4.1 java 客戶端類似的規範,同時不要使用低版本的 Linux 核心,採用 3.x 以上核心版本,就可以規避該問題的存在。

5. Mongodb 核心原始碼設計與實現分析

本文相關的Mongodb執行緒模型及隨機數演算法實現相關原始碼分析如下:

mongodb動態執行緒模型原始碼設計與實現分析

mongodb一個連結一個執行緒模型原始碼設計與實現分析

mongodb核心態及使用者態隨機數演算法實現分析

 





來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69984922/viewspace-2727671/,如需轉載,請註明出處,否則將追究法律責任。

相關文章