天天看點

MongoDB Secondary 延時高(同步鎖)問題分析

secondary 拉取到一批 oplog 後,在重放這批 oplog 時,會加一個特殊的 <code>lock::parallelbatchwritermode</code> 的鎖,這個鎖會阻塞所有的讀請求,直到這批 oplog 重放完成。這麼做的原因有2個

盡量避免髒讀,等一批 oplog 重放完後,這批資料才允許使用者讀到。

基于上述問題,某些使用者在讀取備節點時,可能遇到因為 secondary 重放 oplog 占用特殊鎖時間較長,導緻讀取的延時變長。

上述場景除了會影響 secondary 上的讀請求,如果 priamry 上寫請求指定了 writeconcern 來寫多個節點({w: 2+}),而 secondary 又一直阻塞在建立索引上,導緻其後的oplog 重放都要等待建立索引結束,進而主上的寫入也阻塞。

當主上寫入并發很大時,secondary 每次能拉到很多條 oplog,然後并發重放,重放一條的耗時可能很小,但累計起來一次重放上百、上千條 oplog,耗時就會高很多,而重放過程中,secondary 上讀請求都是要阻塞等待的,是以總體看上去,「secondary 上平均延時,可能比 primary 上更長點」(這就是為什麼很多使用者在寫入比較多時,會發現讀secondary 比 讀praimry 更慢),但隻要延時在可接受範圍内,這個問題并無影響,而且根據雲上使用者使用的經驗,絕大部分使用者都是感受不到這個差異的。

但有一種情況值要注意

MongoDB Secondary 延時高(同步鎖)問題分析

從上面的例子可以看到,一條 update 操作,指定了 {multi: true} 選項,更新了2個比對的文檔,針對每個文檔都産生了一條 oplog(主要為了保證 oplog 幂等性),如果比對的文檔有成千上萬條,就會産生對應數量的 oplog,然後 secondary 拉取這些 oplog 并重放;這個場景下,update 的開銷在secondary 上被放大多倍,此時secondary 的讀延時可能會受比較大的影響。

從上述的例子可以看出,secondary 在某些場景下會出現讀延時很高的情況,那麼當實際遇到問題時,如何判斷問題就是 secondary 重放 oplog 占用鎖時間太長導緻呢?

<a href="https://yq.aliyun.com/articles/57755?spm=5176.8091938.0.0.p8qw7y">mongodb複制集同步原了解析</a>

<a href="https://yq.aliyun.com/articles/55821">secondary節點為何阻塞請求近一個小時?</a>

<a href="https://www.aliyun.com/product/mongodb?spm=5176.8142029.388261.35.ayuymx">阿裡雲資料庫 mongodb 版</a>