大數據存儲:MongoDB實戰指南——常見問題解答

 

鎖粒度與併發性能怎麼樣?

數據庫的讀寫併發性能與鎖的粒度息息相關,不論是讀操做仍是寫操做開始運行時,都會請求相應的鎖資源,若是請求不到,操做就會被阻塞。讀操做請求的是讀鎖,可以與其它讀操做共享,可是當寫操做請求數據庫時,它所申請的是寫鎖,具備排它性。算法

MongoDB在2.2以前的版本,鎖的粒度是很是粗的,它會鎖住整個mongod實例。這意味着當一個數據庫上的寫鎖被請求後,對mongod實例上管理的其它數據庫的操做都會被阻塞。2.2版本下降了鎖的粒度,引入了單個數據庫範圍的鎖,也就是說讀寫操做的鎖被限定在單個數據庫上,當一個數據庫被鎖住後,其它數據庫上的操做能夠繼續被執行。儘管相對於全局實例範圍鎖,數據庫範圍鎖性能有所提升,可是對於同一個數據庫大量的併發讀寫仍是會有性能瓶頸出現,本書介紹的2.6版本仍然是數據庫範圍鎖,因此併發性能問題仍然存在。數據庫

在即將發佈的2.8版本中將會引入基於文檔級別的鎖,至關於關係數據庫中的行級鎖,鎖的粒度更進一步變細。所以當一個寫操做發生時,只有涉及到的文檔會被鎖住,若是寫操做涉及到整個集合,那麼將會產生一個集合鎖來鎖住整個集合,同理,若是寫操做涉及多個數據庫,仍然會有一個全局實例鎖產生。數組

是否支持ACID事務?

經典ACID事務有四種特性即Atomicity,Consistency,Isolation和Durability。其中原子性保證了事務的操做要麼所有成功,要麼失敗後進行回滾,使數據庫回到原來的狀態;一致性保證了事務在開始以前和結束之後,數據庫中的數據徹底符合所設置的各類約束和規則;隔離性保證了多個事務操做同一數據時,相互之間按照約定的隔離級別訪問和修改相同的數據,不一樣的關係數據庫會有不一樣的默認隔離級別;持久性保證了事務結束後,事務所涉及到的數據變化被持久的保存在數據庫中,即便斷電重啓數據也會存在,而且是完整的。服務器

MongoDB並不支持ACID事務特性,可是MongoDB支持在單個文檔(記錄)上的原子操做,設計數據模型時,經過文檔嵌套的方式也能解決關係數據庫中ACID事務特性所要求的大多數問題。例如,在關係數據庫中多條相關聯的記錄存儲,能夠經過嵌套數組或文檔的形式做爲一條記錄保存在MongoDB中,這樣至關於實現了原子性。數據結構

 

 

內存映射文件如何工做?

內存映射文件是指調用操做系統的底層函數mmap( )將磁盤上的文件映射到一個操做系統虛擬地址空間中,只是地址與地址之間創建一個映射關係,實際數據還在物理磁盤上,不在內存中。內存映射文件是MongoDB存儲引擎管理數據的核心方法,一旦完成映射,MongoDB對這部分文件數據的訪問,就好像在內存中訪問同樣,經過一個地址就能直接訪問了。併發

MongoDB利用內存映射文件的方式管理和操做全部的數據,若是數據沒有被映射到內存中,則不能被訪問。對已經完成內存映射的文件進行訪問時,若是發現數據不在內存中,則會發生缺頁錯誤,操做系統將經過映射好的地址關係找到在磁盤上的數據文件並將它加載到內存中。分佈式

服務器的內存多大合適?

MongoDB採用內存映射文件的機制來加快數據的讀寫速度,使用操做系統自帶的虛擬內存管理器來管理內存,理論上MongoDB會佔用服務器上全部的空閒內存,但實狀況下的數據文件老是遠大於物理內存的大小,何況可能會有新的進程運行在服務器上,這也須要佔用內存,所以所有將數據文件映射到虛擬地址空間是不可能的。函數

MongoDB在實際運行過程當中,會有一部分常常被客戶端訪問的數據和索引,稱之爲活躍「工做集」,若是能保證這部分「工做集」的數據常駐內存,系統性能將比較高效,不然,大量的磁盤I/O操做將會發生,下降系統性能。所以,服務器的內存大小最少大於「工做集」數據的大小比較合適。當服務器的空閒內存不足時,操做系統會根據內存管理算法將最近最少使用的數據從內存中移除,騰出空間給有須要的數據。 性能

不支持join查詢怎麼辦?

Join查詢是關係數據庫中一種經典的多表聯合查詢的方式,但MongoDB並不支持這種操做。若是你想在多個Collection中檢索數據,那麼你必須作屢次的查詢,若是以爲手動作的查詢太多了,你能夠重設計你的數據模型來減小總體查詢的數量。大數據

MongoDB中的文檔能夠是任何類型,咱們能夠輕易的對數據結構進行重構,這樣就可讓它始終和應用程序保持一致,用一次查詢就能知足需求。切記,避免用關係數據庫的思惟來設計MongoDB的表結構。

複製集提供了數據冗餘功能爲何還要用Journaling?

Journaling是特別有用的當數據庫遇到忽然斷電等異常狀況時,尤爲是對只有單個節點的數據中心,它能使數據庫快速的恢復起來。Journaling相似關係數據庫MySql中的事務日誌功能,它與複製集的冗餘功能不同,後者更強調的是一種數據備份,而journaling偏向與數據庫災難恢復。關於Journaling的工做機制,請參考本書第5章。

何時該用GridFS?

GridFS本質上仍是基於MongoDB的collection和document等核心技術的,只是它會將大於16MB的文件分割成許多小文件,而後將這些小文件存儲在相應的collection中。若是須要存儲的單個文件的大小超過16MB,就應該用MongoDB自帶的GridFS系統,有的時候將大文件存儲在MongoDB的GridFS中比直接存在操做系統的文件系統中要更加高效;若是須要存儲的文件數超過了操做系統中一個目錄下容許包含的文件總數,則能夠用GridFS系統;當你想要將你的文件分佈式部署在各個數據中心並提供冗餘保護時,能夠用GridFS系統。

此外,當你的全部文件大小都小於16MB時,不要用GridFS系統,由於將每一個文件保存在一個document中每每會更高效。

分片集羣如何分發查詢請求的?

如何分發查詢請求在一個分片集羣上取決於集羣的配置和查詢語句自己。例如一個被分片的集合,有兩個字段:user_id和user_name,其中user_id爲分片的片鍵,當一個查詢語句利用user_id做爲過濾條件返回結果時,mongos路由進程將先利用配置服務器上的元信息解析出須要從哪一個或哪幾個片上獲取數據,而後直接將查詢請求定向到具體的片上,最後返回結果給客戶端;當一個查詢利用user_id做爲過濾條件同時要求對查詢結果進行排序時,mongos先將查詢請求路由到具體的片上,並在各個片上完成排序,最後mongos將合併排序結果返回給客戶端;當一個查詢利用user_name做爲過濾條件時,則查詢請求將被定向到全部的片上,mongos合併各片上查詢結果返回給客戶端。

複製集從故障中自動恢復要多久?

複製集從故障中恢復並選擇一個新的primary節點大約需1分鐘的時間。一般其它成員節點將會花大約10到30秒的時間發送心跳包到發生故障的primary節點,判斷primary節點發生了故障;接着觸發一個選舉,大約再花10到30秒的時間選舉出新的primary節點,在選舉的過程當中,複製集不能響應寫操做請求。若是配置了容許客戶端從其它secondary節點讀取,則在選舉的過程當中複製集可以響應客戶端的讀請求。

爲何磁盤分配的空間大於數據庫中數據大小?

這主要有如下幾方面的緣由:

(1)MongoDB存儲引擎採起預分配數據文件機制,這樣可以減小文件系統的碎片。MongoDB將第一個數據文件命名爲<數據庫名>.0,第二個命名爲<數據庫名>.1,依次類推下去。第一個文件的大小爲64MB,第二個爲128MB,後面分配的文件大小都是前面一個的兩倍,這樣會致使最後分配的數據文件可能會有部分空間是沒有保存數據庫數據的,所以會浪費一點磁盤空間。

(2)若是mongod實例是複製集的成員,則會在數據目錄下產生一個oplog.rs文件,文件中包含用來同步數據的操做日誌,相似於MySql中的二進制日誌,這個文件的大小約佔5%的磁盤空間,它是能夠被重複使用的。

(3)數據目錄中還會包含journal文件,在寫做的更改刷新到數據文件以前,用來保存寫操做日誌,實現數據庫的恢復功能,相似於MySql中的redo日誌。

(4)當刪除一些集合或文檔時,MongoDB存儲引擎會重用這部分數據空間,可是不會把這部分空間返還給操做系統,除非執行repairDatabase命令。

因此mongod實例佔用的磁盤空間大小老是大於數據庫中數據文件的大小。

大數據存儲:MongoDB實戰指南

相關文章
相關標籤/搜索