MongoDB--副本集基本資訊【面試必備】
副本集的概念
副本集是一組伺服器,其中有一個是主伺服器(primary),用於處理客戶端請求;還有多個備份伺服器(secondary),用於儲存主伺服器的資料副本。如果主伺服器崩潰了,備份伺服器會自動將其中一個成員升級為新的主伺服器。
副本集特徵:
· N 個節點的叢集
· 任何節點可作為主節點
· 所有寫入操作都在主節點上
· 自動故障轉移
· 自動恢復
副本集還有以下幾個需要注意的地方:
1. 最小構成是:primary,secondary,arbiter,一般部署是:primary,2 secondary。
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 }
&n