MongoDB的安全寫入GetLastError

  此次聊聊業務中常常出現的重試現象,可能不少運維都被開發莫名其妙的艾特而後讓查一查業務中出現失敗的狀況,很不巧剛接手MongoDB的運維就碰到了一個案例。mongodb

  前段時間與業務開發討論過某業務服務的超時重試問題,這項業務依賴的數據庫是一直很熱門的MongoDB數據庫,這裏採用了複製集的模式架構,且底層硬件採用KVM。業務開發反映數據庫實例慢,最近超時的業務較少,重試後都能正常進行。我與開發溝通了半小時後大體瞭解他的意思,又花了大半天的時間去溝通並解決這個問題,過程就不詳細贅述了。大概的意思就是這項短信服務平臺業務實時性要求很是高,出現過一些業務超時現象,重試後仍然都能執行成功,但願咱們排查下問題並對MongoDB集羣進行一次優化。經i過與業務開發進一步的溝通,知曉他的需求和業務邏輯後,初步判斷問題不出如今數據庫集羣在,業務邏輯並無真正的串行話執行,意思就是B發生的前提是A發生了,然而這裏程序設計沒有去判斷這個A有沒有發生就去執行B。另外一個問題是他以爲所謂的慢,經過超時現象變少,業務場景要求的實時性採用讀寫分離添加secondary節點知足他的橫向擴容並不能有效解決他的問題,這些經過監控和服務器的CPU、IO、數據庫實例的真實負載均可以看到性能沒有到瓶頸。數據庫

  最終我完善了集羣的延遲監控,發現最多有1s到2s的延遲,且這個延遲反覆出現,顯然這個現象並不能經過secondary節點來緩解他的超時問題,對於這種實時性很是高的業務咱們能夠經過採用更好的硬件去解決或者其餘優化手段。對於MongoDB的寫入,我查閱了部分資料也建議他採用getlasterror的程序判斷寫入MongoDB是否成功,以及完善業務邏輯兩種措施解決。安全

  對於getlasterror的安全寫入問題,總結以下,僅供參考閱讀:服務器

getlasterror的安全寫入
  Mongodb的寫操做默認是沒有任何返回值的,這減小了寫操做的等待時間,也就是說,無論有沒有寫入到磁盤或者有沒有遇到錯誤,它都不會報錯。但通常咱們是不放心這麼作的,這時候就調用getlastError命令,獲得返回值。
  getLastError 是Mongodb的一個命令,它好像是取得最後一個error,但其實它是Mongodb的一種客戶端阻塞方式,用這個命令來得到寫操做是否成功的信息。getlastError有幾個參數:j,w,fsync。
  在多線程模式下讀寫Mongodb的時候,若是這些讀寫操做是有邏輯順序的,那麼這時候也有必要調用getlasterror命令,用以確保上個操做執行完下個操做才能執行,由於兩次執行的鏈接有多是不一樣的。在大多數狀況下,咱們都會使用鏈接池去鏈接mongodb,因此這是須要注意的。

getlasterror的最佳實踐網絡

  一、若是沒有特殊要求,最低級別也要使用WriterConcern.SAFE,即w=1。多線程

  二、對於不重要的數據,好比log日誌,可使用WriterConcern.NONE或者WriterConcern.NORMAL,即w=-1或者w=0,省去等待網絡的時間。架構

  三、對大量的不連續的數據寫入,若是每次寫入都調用getLastError會下降性能,由於等待網絡的時間太長,這種狀況下,能夠每過N次調用一下getLastError。可是在Shard結構上,這種方式不必定確保以前的寫入是成功的。併發

  四、對連續的批量寫入(batchs of write),要在批量寫入結束的時候調用getlastError,這不只能確保最後一次寫入正確,並且也能確保全部的寫入都能到達服務器。若是連續寫入上萬條記錄而不調用getlastError,那麼不能確保在同一個TCP socket裏全部的寫入都成功。這在併發的狀況下可能就會有問題。避免這個併發問題運維

  五、對數據安全要求很是高的的配置:j=true,w="majority" db.runCommand({getlasterror:1,j:true,w:'majority',wtimeout:10000})socket

  對於getlasterror是否採用,須要考慮業務的具體場景和業務邏輯設計,並非全部的場景都能適用。以我此次遇到的案例,對於短信類的服務平臺,自己對實時性要求很是高,且會調用第三方的短信服務平臺,邏輯存在漏洞可是爲了保證明時性,數據庫層面不建議他進行這樣的安全寫入機制,業務開發也以爲這種限制不可行。

相關文章
相關標籤/搜索