大數據存儲: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實戰指南

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM