MongoDB--副本集基本資訊【面試必備】

低調人生發表於2019-05-16

副本集的概念

副本集是一組伺服器,其中有一個是主伺服器(primary),用於處理客戶端請求;還有多個備份伺服器(secondary),用於儲存主伺服器的資料副本。如果主伺服器崩潰了,備份伺服器會自動將其中一個成員升級為新的主伺服器。

副本集特徵:
  · N 個節點的叢集
  · 任何節點可作為主節點
  · 所有寫入操作都在主節點上
  · 自動故障轉移
  · 自動恢復
副本集還有以下幾個需要注意的地方:
  1. 最小構成是:primary,secondary,arbiter,一般部署是:primary,2 secondary。
  2. 成員數應該為奇數,如果為偶數的情況下新增arbiter,arbiter不儲存資料,只投票。
  3. 最大50 members,但是隻能有 7 voting members,其他是non-voting members。

 

1、資料同步
    Mongo的複製功能是通過oplog實現的oplog包含了主節點的每一次寫操作,是主節點的local資料庫中的一個固定集合,備份節點通過查詢這個集合就可以知道需要進行復制的操作。每個備份節點有自己的oplog,這樣每個成員就可以當作同步源提供給其他成員使用。備份節點從當前同步源中獲取需要執行的操作,然後在自己的資料集上執行這些操作,最後將這些操作寫入自己的oplog。

    如果備份節點掛了,當它重啟後,會自動從oplog中最後一個操作開始同步,由於複製操作的過程是先複製資料再寫入oplog,所以備份節點有可能在已經同步過的資料上再次執行復制操作。Mongo是這麼處理的:將oplog中的同一操作執行多次與只執行一次的效果是一樣

    由於oplog大小是固定的,通常它的使用空間的增長速度與系統處理寫請求的速率近乎相同。但是有些例外情況:如果單次處理能夠影響到多個文件,那麼每個受影響的文件都會對應oplog的一條日誌。比如執行db.coll.remove()刪除了1000000個文件,那麼oplog中就會有1000000條操作日誌,這樣oplog很快就會被填滿。

 

2、仲裁節點
  仲裁者唯一的作用就是選舉,不儲存資料,也不會為客戶端提供服務,它只是為了滿足“大部分”的要求

  新增仲裁者的兩種方式

    >rs.addArb(“server-5:27017”)

    >rs.add({“_id”:4,”host”:” server-5:27017”,”arbiterOnly”:true})

 

 仲裁的缺點

    比如有三個成員的副本集,其中一個是仲裁節點。當一個資料節點掛了,那麼另一個資料節點成為主節點,為了保證資料安全,就需要新增一個新的備份節點,但由於仲裁節點無資料,那麼新節點的資料傳輸只能靠當前的主節點完成。那麼它不僅要處理應用程式請求,還要資料複製到備份節點,會造成伺服器壓力巨大

    所以儘量配置成奇數個資料成員,而不使用仲裁者

 

 

3、優先順序
  優先順序表示一個成員渴望成為主節點的程度,取值範圍0-100,預設1,0代表永遠不能成為主節點(passive member)

  優先順序別高的會優先選舉為主節點(只要他能得到大部分的支援,並且資料是最新的)

4、心跳
  每個成員每隔兩秒都會向其他成員傳送一個心跳請求,用於檢查每個成員的狀態,知道自己是否符合大多數的條件。

 

5、回滾
  如果主節點執行了一次寫請求後掛了,但是備份節點還沒來得及複製這次操作,那麼新選舉出來的主節點就會漏掉這次寫操作。這時就會執行回滾過程。

 

6、記憶體管理mmap

  mongodb的所有資料實際上是存放在硬碟的,所有要操作的資料通過mmap的方式對映到記憶體某個區域內。
  然後,mongodb就在這塊區域裡面進行資料修改,避免了零碎的硬碟操作。
  至於mmap上的內容flush到硬碟就是作業系統的事情了,所以,如果,mongodb在記憶體中修改了資料,然後,mmap資料flush到硬碟之前,系統當機了,就會丟失資料了。
 
  mysql,無論資料還是索引都存放在硬碟中。到要使用的時候才交換到記憶體中。能夠處理遠超過記憶體總量的資料。
 
  資料量和效能
    當實體記憶體夠用的時候,redis》mongodb》mysql
 
  mysql墊底是肯定的。至於,redis為什麼比mongodb快。還是跟場景和使用業務有關係的。
  大部分情景下,由於mongodb要兼顧它特有的弱表結構下複雜的查詢,在很多存取過程上做了妥協。
  其實,這裡並不想說redis和mongodb的效能怎樣,只想說明下隨著資料量的增長,redis和mongodb,mysql是怎麼變化的。
 
  當實體記憶體不夠用的時候
  redis和mongodb都會使用虛擬記憶體。
  實際上如果redis要開始虛擬記憶體,那很明顯要麼加記憶體條,要麼你換個資料庫了。
  但是,mongodb不一樣,只要,業務上能保證,冷熱資料的讀寫比,使得熱資料在實體記憶體中,mmap的交換較少。mongodb還是能夠保證效能。有人使用mongodb儲存了上T的資料。
  mysql,mysql根本就不需要擔心資料量跟記憶體下的關係。不過,記憶體的量跟熱資料的關係會極大地影響效能表現。
 
  當實體記憶體和虛擬記憶體都不夠用的時候
  估計除了mysql你沒什麼好選擇了。
 
 
  其實,從資料儲存原理來看,我更傾向於將mongodb歸類為硬碟資料庫,但是使用了mmap作為加速的手段而已。

       MongoDB應該分配的記憶體大小最好滿足記憶體大小>索引+熱資料+連線佔用記憶體,通過db.stats()命令可檢視到當前資料庫的索引大小情況
     db.stats()

      下面是公司的MongoDB儲存了14億資料,佔1.4T儲存空間

shard1:SECONDARY> db.stats()
{
    "db" : "database",            // 當前使用的資料庫 
    "collections" : 662,             // 多少張表 
    "objects" : 1405948982,         // 所有表的多少條資料      -- 14.05億
    "avgObjSize" : 1134.649427176014,    // 平均每條資料大小       
    "dataSize" : 1595259207065,      // 總資料大小         -- 1.485TB
    "storageSize" : 768647647232,     // 所有資料佔磁碟的大小    -- 715.85G
    "numExtents" : 0,
    "indexes" : 1098,            // 索引數量
    "indexSize" : 173431967744,      // 索引大小          -- 160G
    "ok" : 1
}

 

相關文章