1. 程式人生 > >mongodb丟失資料的原因剖析

mongodb丟失資料的原因剖析

1.之前用mongodb資料的時候,有時候會有丟失,一開始考慮到是mongodb的安全效能不行嗎,在網上看了一些資料,做了一些解釋:

MongoDB確實在其發展的過程中,有一些資料持久化的問題沒有處理好,特別是一些預設值的選定上。大部分使用者會拿來就用,直到遇到問題之後才發現他們應該在開始的時候做一些必要的配置。但是,所有這些已經被發現的問題也好,預設設定也好,已經在 MongoDB 2.6以後得到了妥善的解決。我可以負責任地告訴你,你看到的資料安全問題,基本上都是2.4或者之前版本的問題或者是使用者配置的問題。接下來我們來仔細分析一下MongoDB的資料安全機制,通過這個分析來更好地理解為什麼有丟資料問題的說法,以及如何來正確的配置MongoDB來保證資料的安全。
MongoDB的資料安全包括以下幾個概念:
恢復日誌(Journal)
寫關注(Write Concern)
恢復日誌
在MySQL, PostgreSQL,Oracle等關係型資料庫裡都有一個Write Ahead Log(Redo Log)的機制用來解決因為系統掉電或者崩潰時導致記憶體資料丟失問題。MongoDB 的journal就是實現這個目的的一種WAL日誌。在MongoDB 2.0之前,Journal沒有被支援或者不是一個預設開的選項。所以當你進行寫入操作時。在沒有Journal的情況下,MongoDB是這樣儲存資料的:


簡單來說,資料在寫入記憶體之後即刻返回給應用程式。而資料刷盤動作則在後臺由作業系統來進行。MongoDB會每隔60秒強制把資料刷到磁碟上。那麼大家可以想象得到,如果這個時候發生了系統崩潰或者掉電,那麼未刷盤的資料就會徹底丟失了。如果大家看到的部落格是2011年左右的,那基本上是碰到了這種情況。
自從2.0開始,MongoDB已經把Journal日誌設為預設開啟。

在上圖的情況下,MongoDB會先把資料更新寫入到Journal Buffer裡面然後再更新記憶體資料,然後再返回給應用端。Journal會以100ms的間隔批量刷到盤上。這樣的情況下,即使出現斷電資料尚未儲存到檔案,由於有Journal檔案的存在,MongoDB會自動根據Journal裡面的操作歷史記錄來對資料檔案重新進行追加。
有細心的同學可能注意到,Journal檔案是100ms 刷盤一次。那麼要是系統掉電正好發生在上一次刷journal的50ms之後呢?這個時候,我們就可以來看一下MongoDB持久化的下一個概念了:寫關注
寫關注(Write Concern)
寫關注(或翻譯為寫安全機制)是MongoDB特有的一個功能。它可以讓你靈活地指定你寫操作的持久化設定。這是一個在效能和可靠性之間的一個權衡。 寫關注有以下幾個級別:
{w: 0} Unacknowledged

Unacknowledged指的是對每一個寫入操作,MongoDB並不會返回一個是否成功的狀態值。這個級別是寫入效能最好但也是最不安全的級別。比如說,你試圖插入一個違反了唯一性的文件(重複的身份證號),那麼MongoDB會拒絕寫入並報錯。但是由於驅動端並沒有在乎你的報錯,應用程式還滿心歡喜以為一切都沒問題,下回再來查詢那條資料的時候就會出現資料缺失的情況。
有不少時候MongoDB用來儲存一些監控和程式日誌資料,這個時候如果你有1、2條資料丟失,是不會對應用程式有什麼影響的。基於這些MongoDB早些時候不成熟考量,MongoDB在2.2之前的預設設定就是 {w:0}。這是個讓MongoDB 悔恨無比的選擇,因為這個是很多人覺得MongoDB資料不安全的根本原因。
在MongoDB 2.4,這個設定已經被改為下面的 {w:1}
{w: 1} Acknowledged

Acknowledged 的意思就是對每一個寫入MongoDB都會確認操作的完成狀態,不管是成功還是失敗。當然這個確認只是基於主節點的記憶體寫入。但就是這個級別,可以偵測到重複主鍵, 網路錯誤,系統故障或者是無效資料等錯誤。
自2.4版本起,MongoDB的預設寫安全設定就是 {w:1} Acknowledged。在這種情況下,出現因為系統故障掉電原因而導致的資料丟失只會是我們早些提到的日誌沒有及時刷盤的情況。如果你不能接受因為系統崩潰而引起的可能的100ms的資料損失,那麼你可以選用下一個級別: {j:1} Journaled
{j:1} Journaled

使用這種方式意味著每一次的寫操作會在MongoDB實實在在的把journal落盤以後才會返回。當然這並不意味著每一個寫操作就等於一個IO。MongoDB並不會對每一個操作都立即刷盤,而是會等最多30ms,把30ms內的寫操作集中到一起,採用順序追加的方式寫入到盤裡。在這30ms內客戶端執行緒會處於等待狀態。這樣對於單個操作的總體響應時間將有所延長,但對於高併發的場景,綜合下來平均吞吐能力和響應時間不會有太大的影響。特別是你能給journal部署一個對順序寫有優化的IO頻寬足夠的專門的儲存系統的話,這個對效能的影響可以降到最低。
那麼使用 {j:1} 是不是就100% 安全了呢?如果是單機版本,這個基本上就是可以確保的了(除非硬碟損壞)。可是在複製集的場景下,我們還需要來考慮一種更高的級別: {w: “majority”}
{w: “majority”} 寫到多數節點
MongoDB 的預設部署是至少3個節點的複製集(Replicaset)。使用複製集的好處很多,最關鍵的就是提高系統的高可用性。另外一個好處就是提供資料的永續性。在複製集下哪怕你的整個主機連記憶體帶硬碟壞掉,你的資料還是健康的存在在第二臺或者第N臺從節點上。但是複製集作為一種分散式的架構也對我們資料一致性提出了新的挑戰。以上述的{w: 1} 寫安全配置為例,我們來分析一種比較複雜的場景。

01:00:00 網路故障,主從之間網路斷開
01:00:01 應用寫入一個文件: {ts: “01:00:01〃} 注意這個文件無法複製到B和C。此時主節點尚未完全確認網路已故障,所以按照{w:1}規則繼續接受並確認寫入。
01:00:02 主節點A意識到自己無法和從節點B,C 聯絡上,主動降級為從節點,停止接受寫操作
01:00:05 B,C 選舉結果成功,B升級為主節點。B開始接受寫操作。{ts: “01:00:06〃}
01:00:08 網路恢復,A重新加入叢集。這個時候A的oplog 和B的oplog已經有不一致了。A會主動把B上面不存在的寫操作回滾掉(rollback),並寫入一個回滾檔案。
在這個時候應用如果再去查詢 {ts: “01:00:01〃}這個文件,MongoDB 將會說文件不存在!
怎麼辦怎麼辦? {w: “majority”} 就是我們的答案。 “majority” 指的是“大多數節點”。使用這個寫安全級別,MongoDB只有在資料已經被複制到多數個節點的情況下才會向客戶端返回確認。

我們來看一下在使用 {w: “majaority”} 之後,剛才的情況就變成了:
01:00:00 網路故障,主從之間網路斷開
01:00:01 應用要求寫入一個文件: {ts: “01:00:01〃} 文件會首先成功寫入主節點。但是由於網路斷開這個文件無法複製到B和C。因為無法滿足{w:”majority”}要求,從應用的角度這個文件並沒有寫入成功。
01:00:02 主節點A意識到自己無法和從節點B,C 聯絡上,主動降級為從節點,停止接受寫操作
01:00:05 B,C 選舉結果成功,B升級為主節點。B開始接受寫操作。{ts: “01:00:06〃}
01:00:08 網路恢復,A重新加入叢集。這個時候A會產生回滾,把{ts: “01:00:01〃}這個文件刪除。 此時叢集的資料狀態為一致和正確的。
至此,如果使用 {w: “majority”, j:1 }, 那麼MongoDB可以滿足所有級別資料永續性的要求。值得注意的是在2013年5月Kyle Kingsly 發表了一篇部落格 Call Me Maybe:http://aphyr.com/posts/284-call-me-maybe-mongodb在這片文章裡Kyle 彙報了一些關於 {w: “majority”} 的bug, 這些bug已經在2.6裡被解決了。當然像Sven那樣的譁眾取寵之流,估計並沒有去研究3.0裡面是否真的有問題,而是隨便google了一下幾年前的東西來做文章。
總結
一般來說,MongoDB建議在叢集中使用 {w: “majority”} 設定。在一個叢集是健壯的部署的情況下(如:足夠網路頻寬,機器沒有滿負荷),這個可以滿足絕大部分資料安全的要求,因為MongoDB的複製在正常情況下是毫秒級別的,往往在Journal刷盤之前已經複製到從節點了。如果你追求完美,那麼可以再進一步使用{j:1} 。兩者相結合,
傳說中MongoDB 丟資料的事情,確實已經成為傳說了。
後記:在我寫這篇文章之時,社群又有人彙報資料丟失的問題。說的是每一萬條記錄就會丟一兩條記錄。對於這種情況,我的第一反應就是:查查你的程式碼吧,很多時候往往問題出在程式上。果不其然,經過仔細檢查,原來是程式碼的問題。

相關推薦

mongodb丟失資料原因剖析

1.之前用mongodb資料的時候,有時候會有丟失,一開始考慮到是mongodb的安全效能不行嗎,在網上看了一些資料,做了一些解釋: MongoDB確實在其發展的過程中,有一些資料持久化的問題沒有處理好,特別是一些預設值的選定上。大部分使用者會拿來就用,直到遇到問題之後才發

7種導致陣列資料丟失原因/不可不防

在資料恢復工作中經常能遇到伺服器磁碟陣列資料恢復的案例,本文為大家介紹一下不同raid磁碟陣列資料恢復的型別和原因分析。 1、磁碟陣列處於降級狀態時未及時rebuild磁碟陣列: RAID磁碟陣列的資料安全冗餘原理是利用空餘出的部分空間實現的,當陣列中有成員盤下線後便無法繼續提供冗餘儲存。如

EEPROM資料丟失原因與對策

選用比MCU的電源範圍寬並有WP引腳的EEPROM晶片的原因: 1、EEPROM的晶片本身有一定的保護時序; 2、電源低於MCU工作電源高於EEPROM晶片的最低工作電源時,EEPROM晶片會處於穩定狀態,不會丟失資料。 3、當電源較長時間低於EEPROM晶片的最低工作電壓時非常容易丟失全部資料。否則MCU還

Bmob插入資料顯示Error400錯誤的原因剖析

解決方法: 增加一個檔案:BmobApplication.java package com.example.foolishfan.user_v10; import android.app.Applic

導致硬碟資料丟失原因和恢復資料的方法彙總

故障一:"磁碟未被格式化,是否格式化"[適用介質]   1、典型地-行動硬碟、U盤、數碼卡(相機、手機等)、MP3;   2、普通硬碟;   3、很少的-盤陣等採用WINDOWS系統的儲存;[故障表現]   1、行動硬碟或U盤等,未正常關閉狀態下直接拔下,下次接入系統後雙擊碟

MongoDB 副本集丟失資料的測試

在MongoDB副本集的測試中發現了一個丟資料的案例。 1. 概要描述 測試場景為:一主一從一驗證 測試案例   step1 :關閉從副本; step 2 ;向主副本中插入那條資料; step 3 :關閉主副本; step 4 :開啟輔助副本,此副本升級為主副本,這是後會

【轉載】Android Bug分析系列:第三方平臺安裝app啟動後,home鍵回到桌面後點擊app啟動時會再次啟動入口類bug的原因剖析

特殊 返回 androidm android系統 圖片 管理 相關 OS 簡便 前言   前些天,測試MM發現了一個比較奇怪的bug。   具體表現是:   1、將app包通過電腦QQ傳送到手機QQ上面,點擊安裝,安裝後選擇打開app (此間的應用邏輯應該是要觸發 【閃屏頁

硬盤數據丟失原因和恢復方法

擴展 window lin 判斷 分析 分區 優先 下一步 硬盤數據丟 一、數據丟失的原因及特征 造成數據丟失的原因大致可以分為三大類:軟件、硬件和網絡。 1.硬件方面的起因有突然斷電、磁盤劃傷、磁組損壞、芯片及其它原器件燒壞等。具體表現為硬盤不認,盤體有異常響聲或電機不轉

造成SD卡數據丟失原因和恢復數據方法

sd卡 因此 對數 進行 無法 感染 支持 問題 功能 造成SD卡數據丟失的原因 為什麽SD卡的文件會丟失?難道是打開的方式錯誤?或者SD卡不能被電腦讀取?實際上導致SD卡數據丟失的因素各種各樣,只有搞清楚了狀況和原因,方能更好地解決問題,其中包括如下: 因素一:插口故障 

MongoDB 學習資料整理 MongoDB 學習資料整理

MongoDB 學習資料整理 官網:​https://www.mongodb.org/ 下載:​https://www.mongodb.org/downloads/ 文件:​http://docs.mongodb.org/manual/

03 -2 numpy與pandas中isnull()、notnull()、dropna()、fillna()處理丟失資料的理解與例項

引入三劍客 import numpy as np import pandas as pd from pandas import Series,DataFrame 處理丟失資料 1.有兩種丟失資料: None: Python自帶的資料型別 不能參與到任何計算中

MongoDB資料排序後匯出csv檔案

mongoexport -h 127.0.0.1:27017 -d NBSCPR -c town --sort {'code':1} --type=csv -f code,name,link -o town.csv 引數說明: -h 資料地址:埠 -c 資料庫集合名稱

MySQL二階段提交以及xtrabackup如何保證備份不丟失資料

MySQL二階段提交與xtrabackup如何保證備份不丟失資料 MySQL二階段提交與crash recovery 1. MySQL二階段提交 2. crash recovery的實現 xtrabackup如何實現資料不丟失 1.

你說你懂大資料?這幾種常用的幾種大資料架構剖析你會了嗎?

資料分析工作雖然隱藏在業務系統背後,但是具有非常重要的作用,資料分析的結果對決策、業務發展有著舉足輕重的作用。隨著大資料技術的發展,資料探勘、資料探索等專有名詞曝光度越來越高,但是在類似於Hadoop系列的大資料分析系統大行其道之前,資料分析工作已經經歷了長足的發展,尤其是以BI系統為主的資

訊息佇列任務丟失原因

有時:一個非同步處理的操作正常的放到了非同步佇列裡,但是並沒有被處理,或者資料庫用改動,但是消費的binlog日誌並沒有改動資訊,造成這種的原因是什麼?對此進行一定猜測,訊息佇列是不安全的,會丟失任務(如kafka)? 相比之下,寫定時任務,去資料庫裡掃表,拿出處理中的訂單,去挨個輪詢狀

MongoDB匯入資料資料夾(包括bson和json檔案)報錯

MongoDB匯入資料報錯 很多部落格都說在linux下 使用 mongorestore -d db_name 資料夾目錄 就可以匯入資料夾中的內容 記錄一個傻瓜錯誤: mongorestore是一個獨立可執行程式 這個命令不能放在mongo shell裡執行 應該

Python資料處理之(十 三)Pandas 處理丟失資料

建立含 NaN 的矩陣 有時候我們匯入或處理資料, 會產生一些空的或者是NaN資料,如何刪除或者是填補這些 NaN 資料就是我們今天所要提到的內容. 建立了一個6X4的矩陣資料並且把兩個位置置為空. >>> dates=pd.date_range('20181

msvcp110d.dll 丟失問題原因及解決思路

轉自https://blog.csdn.net/doubaijun/article/details/50599914 https://www.cnblogs.com/lisuyun/p/6410393.html 一般用vs生成的程式在安裝了vs執行包的電腦上也會報出來這個錯誤,很多人不

mongodb資料型別

MongoDB的資料,在我們學習增刪改查的時候就已經體現出來了;; 首先我們先了解一下MongoDB中有什麼樣的資料型別: Object  ID :Documents 自生成的 _id String: 字串,必須是utf-8 Boolean:布林值,true 或者false (這裡有坑哦~在

解決 Eclipse 啟動卡在 Loading 畫面 不丟失資料的解決方案

作業系統:Mac OS Sierra Eclipse版本:Version: Neon.1a Release (4.6.1)   開機卡在Loading 頁面,無響應 造成這種原因多半是因為上一次異常關閉Eclipse造成的   解決方案 1、不