1. 程式人生 > 實用技巧 >mongodb 主從複製,副本集

mongodb 主從複製,副本集

在mongodb中有兩種資料冗餘方法 1 種是master-slave(主從複製)另一種是replice sets(副本集)

Mongodb一共有三種叢集搭建的方式:

Replica Set(副本集)、 Sharding(切片) Master-Slaver(主從)【目前已不推薦使用了!!!】 其中,Sharding叢集也是三種叢集中最複雜的。 副本集比起主從可以實現故障轉移!!非常使用! mongoDB目前已不推薦使用主從模式,取而代之的是副本集模式。副本集其實一種互為主從的關係,可理解為主主。在新版本中已經不在支援 副本集指將資料複製,多份儲存,不同伺服器儲存同一份資料,在出現故障時自動切換。對應的是資料冗餘、備份、映象、讀寫分離、高可用性等關鍵詞;
而分片則指為處理大量資料,將資料分開儲存,不同伺服器儲存不同的資料,它們的資料總和即為整個資料集。追求的是高效能。 在生產環境中,通常是這兩種技術結合使用,分片+副本集。 一、先說說mongodb主從複製配置 主從複製是MongoDB最常用的複製方式,也是一個簡單的資料庫同步備份的叢集技術,這種方式很靈活.可用於備份,故障恢復,讀擴充套件等.
最基本的設定方式就是建立一個主節點和一個或多個從節點,每個從節點要知道主節點的地址。採用雙機備份後主節點掛掉了後從節點可以接替主機繼續服務。所以這種模式比單節點的高可用性要好很多。

配置時注意:

1)在資料庫叢集中要明確的知道誰是主伺服器,主伺服器只有一臺. 需手動在配置檔案中指定

2)從伺服器要知道自己的資料來源也就是對應的主服務是誰.

3)--master用來確定主伺服器,--slave 和 --source來控制從伺服器

佈置 過程:

1 1 下載mongodb的壓縮包,這進行二進位制安裝,可以參考前邊的安裝
2)主從配置 .............master-node節點配置............. [root@master-node ~]# vim /usr/local/mongodb/mongodb.conf port=27017 bind_ip = 182.48.115.238 dbpath=/usr/local/mongodb/data logpath=/usr/local/mongodb/log/mongo
.log logappend=true journal =true fork =true master =true//確定自己是主伺服器 啟動 [root@master-node ~]# nohup /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf & [root@master-node ~]# ps -ef|grep mongodb root 15707 15514 23 16:45 pts/200:00:00/usr/local/mongodb/bin/mongod--config/usr/local/mongodb/mongodb.conf root 15736 15514 0 16:45 pts/200:00:00grepmongodb [root@master-node ~]# lsof -i:27017 COMMAND PID USER FD TYPE DEVICE SIZE/OFFNODE NAME mongod 15707 root 7u IPv4 153114 0t0 TCP 182.48.115.238:27017 (LISTEN) .............slave-node節點配置............. [root@slave-node ~]# vim /usr/local/mongodb/mongodb.conf port=27017 dbpath=/usr/local/mongodb/data logpath=/usr/local/mongodb/log/mongo.log logappend=true journal =true fork =true bind_ip = 182.48.115.236//確定主資料庫埠 source= 182.48.115.238:27017//確定主資料庫埠 slave =true//確定自己是從伺服器 啟動檢視程序 [root@slave-node ~]# nohup /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf & [root@slave-node ~]# ps -ef|grep mongo root 26290 26126 8 16:47 pts/000:00:00/usr/local/mongodb/bin/mongod--config/usr/local/mongodb/mongodb.conf root 26316 26126 0 16:47 pts/000:00:00grepmongo [root@slave-node ~]# lsof -i:27017 COMMAND PID USER FD TYPE DEVICE SIZE/OFFNODE NAME mongod 26290 root 7u IPv4 663904 0t0 TCP slave-node1:27017 (LISTEN) mongod 26290 root 25u IPv4 663917 0t0 TCP slave-node1:51060->slave-node2:27017 (ESTABLISHED) 在slave-node測試連線master-node的mongodb資料庫是否正常 [root@slave-node ~]# mongo 182.48.115.236:27017 3)主從資料同步測試 在master-node節點資料庫裡建立master_slave庫,並插入20條資料 [root@master-node ~]# mongo 182.48.115.238:27017 > use master_slave switched to db master_slave >functionadd(){var i = 0;for(;i<20;i++){db.persons.insert({"name":"wang"+i})}} > add() 然後在slave-node節點資料庫裡檢視,是否將master-node寫入的新資料同步過來了 [root@slave-node log]# mongo 182.48.115.236:27017 > rs.slaveOk(); > show dbs admin 0.000GB local0.000GB master_slave 0.000GB wangshibo 0.000GB > use master_slave switched to db master_slave > db.persons.find() 同步成功 注意: 如果在slave-node節點上的資料庫中檢視,有報錯:"errmsg":"not master and slaveOk=false"!!! 首先這是正常的,因為SECONDARY是不允許讀寫的, 在寫多讀少的應用中,使用Replica Sets來實現讀寫分離。 通過在連線時指定或者在主庫指定slaveOk,由Secondary來分擔讀的壓力,Primary只承擔寫操作。 對於replicaset中的secondary 節點預設是不可讀的。 解決辦法: 在slave-node節點資料庫中執行"rs.slaveOk();"命令即可 主從複製的原理 在主從結構中,主節點的操作記錄成為oplog(operation log)。oplog儲存在一個系統資料庫local的集合oplog.$main中,這個集合的每個文件都代表主節點上執行的一個操作。 從伺服器會定期從主伺服器中獲取oplog記錄,然後在本機上執行!對於儲存oplog的集合,MongoDB採用的是固定集合,也就是說隨著操作過多,新的操作會覆蓋舊的操作! 主從複製的其他設定項 --only 從節點指定複製某個資料庫,預設是複製全部資料庫 --slavedelay 從節點設定主資料庫同步資料的延遲(單位是秒) --fastsync 從節點以主資料庫的節點快照為節點啟動從資料庫 --autoresync 從節點如果不同步則從新同步資料庫(即選擇當通過熱添加了一臺從伺服器之後,從伺服器選擇是否更新主伺服器之間的資料) --oplogSize 主節點設定oplog的大小(主節點操作記錄儲存到local的oplog中) 在上面slave-node從節點的local資料庫中,存在一個集合sources。這個集合就儲存了這個伺服器的主伺服器是誰 [root@slave-node mongodb]# mongo 182.48.115.236:27017 ...... > show dbs admin 0.000GB local0.000GB master_slave 0.000GB wangshibo 0.000GB > uselocal switched to dblocal > show collections me sources startup_log > db.sources.find() {"_id": ObjectId("593277a5105051e5648605a3"),"host":"182.48.115.238:27017","source":"main","syncedTo": Timestamp(1496481652, 1) } >

二、Mongodb副本集(Replica Sets)

mongodb 不推薦主從複製,推薦建立副本集(Replica Set)來保證1個服務掛了,可以有其他服務頂上,程式正常執行,幾個服務的資料都是一樣的,後臺自動同步。主從複製其實就是一個單副本的應用,沒有很好的擴充套件性餓容錯性。然而副本集具有多個副本保證了容錯性,就算一個副本掛掉了還有很多個副本存在,並且解決了"主節點掛掉後,整個叢集內會自動切換"的問題。副本集比傳統的Master-Slave主從複製有改進的地方就是它可以進行故障的自動轉移,如果我們停掉複製集中的一個成員,那麼剩餘成員會再自動選舉一個成員,作為主庫。
Replica Set 使用的是 n 個 mongod 節點,構建具備自動的容錯功能(auto-failover),自動恢復的(auto-recovery)的高可用方案。使用 Replica Set 來實現讀寫分離。通過在連線時指定或者在主庫指定 slaveOk,由Secondary 來分擔讀的壓力,Primary 只承擔寫操作。對於 Replica Set 中的 secondary 節點預設是不可讀的。

1)關於副本集的概念

副本集是一種在多臺機器同步資料的程序,副本集體提供了資料冗餘,擴充套件了資料可用性。在多臺伺服器儲存資料可以避免因為一臺伺服器導致的資料丟失。

也可以從硬體故障或服務中斷解脫出來,利用額外的資料副本,可以從一臺機器致力於災難恢復或者備份。 在一些場景,可以使用副本集來擴充套件讀效能,客戶端有能力傳送讀寫操作給不同的伺服器。也可以在不同的資料中心獲取不同的副本來擴充套件分散式應用的能力。 mongodb副本集是一組擁有相同資料的mongodb例項,主mongodb接受所有的寫操作,所有的其他例項可以接受主例項的操作以保持資料同步。 主例項接受客戶的寫操作,副本集只能有一個主例項,因為為了維持資料一致性,只有一個例項可寫,主例項的日誌儲存在oplog。 二級節點複製主節點的oplog然後在自己的資料副本上執行操作,二級節點是主節點資料的反射,如果主節點不可用,會選舉一個新的主節點。 預設讀操作是在主節點進行的,但是可以指定讀取首選項引數來指定讀操作到副本節點。 可以新增一個額外的仲裁節點(不擁有被選舉權),使副本集節點保持奇數,確保可以選舉出票數不同的直接點。仲裁者並不需要專用的硬體裝置。 仲裁者節點一直會儲存仲裁者身份 ........非同步複製........ 副本節點同步直接點操作是非同步的,然而會導致副本集無法返回最新的資料給客戶端程式。 ........自動故障轉移........ 如果主節點10s以上與其他節點失去通訊,其他節點將會選舉新的節點作為主節點。 擁有大多數選票的副節點會被選舉為主節點。 副本集提供了一些選項給應用程式,可以做一個成員位於不同資料中心的副本集。 也可以指定成員不同的優先順序來控制選舉。

一個副本集即為服務於同一資料集的多個 MongoDB 例項,其中一個為主節點,其餘的都為從節點。主節 點上能夠完成讀寫操作,從節點僅能用於讀操作。主節點需要記錄所有改變資料庫狀態的操作,這些記錄 儲存在 oplog 中,這個檔案儲存在 local 資料庫,各個從節點通過此 oplog 來複制資料並應用於本地,保持 本地的資料與主節點的一致。oplog 具有冪等性,即無論執行幾次其結果一致,這個比 mysql 的二進位制日 志更好用。
叢集中的各節點還會通過傳遞心跳資訊來檢測各自的健康狀況。當主節點故障時,多個從節點會觸發一次 新的選舉操作,並選舉其中的一個成為新的主節點(通常誰的優先順序更高,誰就是新的主節點),心跳信 息預設每 2 秒傳遞一次。

心跳檢測:

整個叢集需要保持一定的通訊才能知道哪些節點活著哪些節點掛掉。mongodb節點會向副本集中的其他節點每兩秒就會發送一次pings包,如果其他節點在10秒鐘之內沒有返回就標示為不能訪問。每個節點內部都會維護一個狀態對映表,表明當前每個節點是什麼角色、日誌時間戳等關鍵資訊。如果是主節點,除了維護對映表外還需要檢查自己能否和叢集中內大部分節點通訊,如果不能則把自己降級為secondary只讀節點。 副本集中的副本節點在主節點掛掉後通過心跳機制檢測到後,就會在叢集內發起主節點的選舉機制,自動選舉出一位新的主伺服器 資料同步 副本集同步分為初始化同步和keep複製。初始化同步指全量從主節點同步資料,如果主節點資料量比較大同步時間會比較長。而keep複製指初始化同步過後,節點之間的實時同步一般是增量同步。初始化同步不只是在第一次才會被處罰,有以下兩種情況會觸發: 1)secondary第一次加入,這個是肯定的。 2)secondary落後的資料量超過了oplog的大小,這樣也會被全量複製。 副本集包括三種節點:主節點、從節點、仲裁節點。
1)主節點負責處理客戶端請求,讀、寫資料, 記錄在其上所有操作的 oplog;
2)從節點定期輪詢主節點獲取這些操作,然後對自己的資料副本執行這些操作,從而保證從節點的資料與主節點一致。預設情況下,從節點不支援外部讀取,但可以設定;
   副本集的機制在於主節點出現故障的時候,餘下的節點會選舉出一個新的主節點,從而保證系統可以正常執行。
3)仲裁節點不復制資料,僅參與投票。由於它沒有訪問的壓力,比較空閒,因此不容易出故障。由於副本集出現故障的時候,存活的節點必須大於副本集節點總數的一半,
   否則無法選舉主節點,或者主節點會自動降級為從節點,整個副本集變為只讀。因此,增加一個不容易出故障的仲裁節點,可以增加有效選票,降低整個副本集不可用的
   風險。仲裁節點可多於一個。也就是說只參與投票,不接收復制的資料,也不能成為活躍節點。

官方推薦MongoDB副本節點最少為3臺, 建議副本整合員為奇數,最多12個副本節點,最多7個節點參與選舉。限制副本節點的數量,主要是因為一個叢集中過多的副本節點,增加了複製的成本,反而拖累了叢集
的整體效能。 太多的副本節點參與選舉,也會增加選舉的時間。而官方建議奇數的節點,是為了避免腦裂 的發生。

3)副本集的工作流程

在 MongoDB 副本集中,主節點負責處理客戶端的讀寫請求,備份節點則負責對映主節點的 資料。備份節點的工作原理過程可以大致描述為,備份節點定期輪詢主節點上的資料操作,
然後對 自己的資料副本進行這些操作,從而保證跟主節點的資料同步。至於主節點上的所有 資料庫狀態改變 的操作,都會存放在一張特定的系統表中。備份節點則是根據這些資料進
行自己的資料更新。
oplog介紹
上面提到的資料庫狀態改變的操作,稱為 oplog(operation log,主節點操作記錄)。oplog 儲存在local資料庫的"oplog.rs"表中。副本集中備份節點非同步的從主節點同步 oplog,然後重新 執行它記錄的操作,以此達到了資料同步的作用。

關於 oplog 有幾個注意的地方:

1)oplog 只記錄改變資料庫狀態的操作

2)儲存在 oplog 中的操作並不是和主節點執行的操作完全一樣,例如"$inc"操作就會轉化為"$set"操作

3)oplog 儲存在固定集合中(capped collection),當 oplog 的數量超過 oplogSize,新的操作就會覆蓋就的操作


資料同步
在副本集中,有兩種資料同步方式:
1)initialsync(初始化):這個過程發生在當副本集中建立一個新的資料庫或其中某個節點剛從宕機中恢復,或者向副本集中新增新的成員的時候,預設的,副本集中的節點會從離 它最近的節點複製 oplog 來同步資料,這個最近的節點可以是 primary 也可以是擁有最新 oplog 副本的 secondary 節點。該操作一般會重新初始化備份節點,開銷較大。
2)replication(複製):在初始化後這個操作會一直持續的進行著,以保持各個 secondary 節點之間的資料同步。

當遇到無法同步的問題時,只能使用以下兩種方式進行 initialsync
1)第一種方式就是停止該節點,然後刪除目錄中的檔案,重新啟動該節點。這樣,這個節 點就會執行 initialsync
注意:通過這種方式,sync的時間是根據資料量大小的,如果資料量過大,sync時間就 會很長同時會有很多網路傳輸,可能會影響其他節點的工作
2)第二種方式,停止該節點,然後刪除目錄中的檔案,找一個比較新的節點,然後把該節點目 錄中的檔案拷貝到要sync的節點目錄中通過上面兩種方式中的一種,都可以重新恢復


副本集管理
1)檢視oplog的資訊 通過"db.printReplicationInfo()"命令可以檢視 oplog 的資訊
欄位說明:
configured oplog size: oplog 檔案大小
log length start to end: oplog 日誌的啟用時間段
oplog first eventtime: 第一個事務日誌的產生時間
oplog last eventtime: 最後一個事務日誌的產生時間
now: 現在的時間

2)檢視 slave 狀態 通過"db.printSlaveReplicationInfo()"可以檢視 slave 的同步狀態
當插入一條新的資料,然後重新檢查 slave 狀態時,就會發現sync時間更新了




4)副本集選舉的過程和注意點

Mongodb副本集選舉採用的是Bully演算法,這是一種協調者(主節點)競選演算法,主要思想是叢集的每個成員都可以宣告它是主節點並通知其他節點。
別的節點可以選擇接受這個聲稱或是拒絕並進入主節點競爭,被其他所有節點接受的節點才能成為主節點。
節點按照一些屬性來判斷誰應該勝出,這個屬性可以是一個靜態 ID,也可以是更新的度量像最近一次事務ID(最新的節點會勝出)
 
副本集的選舉過程大致如下:
1)得到每個伺服器節點的最後操作時間戳。每個 mongodb 都有 oplog 機制會記錄本機的操作,方便和主服 務器進行對比資料是否同步還可以用於錯誤恢復。
2)如果叢集中大部分伺服器 down 機了,保留活著的節點都為 secondary 狀態並停止,不選舉了。
3)如果叢集中選舉出來的主節點或者所有從節點最後一次同步時間看起來很舊了,停止選舉等待人來操作。
4)如果上面都沒有問題就選擇最後操作時間戳最新(保證資料是最新的)的伺服器節點作為主節點。
副本集選舉的特點: 選舉還有個前提條件,參與選舉的節點數量必須大於副本集總節點數量的一半(建議副本整合員為奇數。最多12個副本節點,最多7個節點參與選舉) 如果已經小於一半了所有節點保持只讀狀態。集合中的成員一定要有大部分成員(即超過一半數量)是保持正常線上狀態,3個成員的副本集,需要至少2個從屬節點是正常狀態。 如果一個從屬節點掛掉,那麼當主節點down掉 產生故障切換時,由於副本集中只有一個節點是正常的,少於一半,則選舉失敗。 4個成員的副本集,則需要3個成員是正常狀態(先關閉一個從屬節點,然後再關閉主節點,產生故障切換,此時副本集中只有2個節點正常,則無法成功選舉出新主節點)。

5)副本集資料過程

primary節點寫入資料,Secondary通過讀取Primary的oplog得到複製資訊,開始複製資料並且將複製資訊寫入到自己的oplog。如果某個操作失敗,則備份節點
停止從當前資料來源複製資料。如果某個備份節點由於某些原因掛掉了,當重新啟動後,就會自動從oplog的最後一個操作開始同步,同步完成後,將資訊寫入自己的
oplog,由於複製操作是先複製資料,複製完成後再寫入oplog,有可能相同的操作會同步兩份,不過MongoDB在設計之初就考慮到這個問題,將oplog的同一個操作
執行多次,與執行一次的效果是一樣的。簡單的說就是:
當Primary節點完成資料操作後,Secondary會做出一系列的動作保證資料的同步:

1)檢查自己local庫的oplog.rs集合找出最近的時間戳。

2)檢查Primary節點local庫oplog.rs集合,找出大於此時間戳的記錄。

3)將找到的記錄插入到自己的oplog.rs集合中,並執行這些操作。

副本集的同步和主從同步一樣,都是非同步同步的過程,不同的是副本集有個自動故障轉移的功能。其原理是:slave端從primary端獲取日誌,然後在自己身上完全順序
的執行日誌所記錄的各種操作(該日誌是不記錄查詢操作的),這個日誌就是local資料 庫中的oplog.rs表,預設在64位機器上這個表是比較大的,佔磁碟大小的5%,
oplog.rs的大小可以在啟動引數中設 定:--oplogSize 1000,單位是M。

注意:在副本集的環境中,要是所有的Secondary都宕機了,只剩下Primary。最後Primary會變成Secondary,不能提供服務。


6)MongoDB 同步延遲問題

當你的使用者抱怨修改過的資訊不改變,刪除掉的資料還在顯示,你掐指一算,估計是資料庫主從不同步。與其他提供資料同步的資料庫一樣,MongoDB 也會遇到同步延遲的問題,
在MongoDB的Replica Sets模式中,同步延遲也經常是困擾使用者的一個大問題

什麼是同步延遲?

首先,要出現同步延遲,必然是在有資料同步的場合,在 MongoDB 中,有兩種資料冗餘方式,一種是Master-Slave 模式,一種是Replica Sets模式。這兩個模式本質上都是

在一個節點上執行寫操作, 另外的節點將主節點上的寫操作同步到自己這邊再進行執行。在MongoDB中,所有寫操作都會產生 oplog,oplog 是每修改一條資料都會生成一條,如果你採用一個批量 update 命令更新了 N 多條資料, 那麼抱歉,oplog 會有很多條,而不是一條。所以同步延遲就是寫操作在主節點上執行完後,從節點還沒有把 oplog 拿過來再執行一次。而這個寫操作的量越大,主節點與從節點的差別也就越大,同步延遲也就越大了。

同步延遲帶來的問題
首先,同步操作通常有兩個效果,一是讀寫分離,將讀操作放到從節點上來執行,從而減少主節點的 壓力。對於大多數場景來說,讀多寫少是基本特性,所以這一點是很有用的。
另一個作用是資料備份, 同一個寫操作除了在主節點執行之外,在從節點上也同樣執行,這樣我們就有多份同樣的資料,一旦 主節點的資料因為各種天災人禍無法恢復的時候,我們至少還有從節點可以依賴。但是主從延遲問題 可能會對上面兩個效果都產生不好的影響。

如果主從延遲過大,主節點上會有很多資料更改沒有同步到從節點上。這時候如果主節點故障,就有 兩種情況:
1)主節點故障並且無法恢復,如果應用上又無法忍受這部分資料的丟失,我們就得想各種辦法將這部 資料更改找回來,再寫入到從節點中去。可以想象,即使是有可能,那這也絕對是一件非常噁心的活。
2)主節點能夠恢復,但是需要花的時間比較長,這種情況如果應用能忍受,我們可以直接讓從節點提 供服務,只是對使用者來說,有一段時間的資料丟失了,而如果應用不能接受資料的不一致,那麼就只能下線整個業務,等主節點恢復後再提供服務了。

如果你只有一個從節點,當主從延遲過大時,由於主節點只儲存最近的一部分 oplog,可能會導致從 節點青黃不接,不得不進行 resync 操作,全量從主節點同步資料。
帶來的問題是:當從節點全量同步的時候,實際只有主節點儲存了完整的資料,這時候如果主節點故障,很可能全 部資料都丟掉了。

7)Mongodb副本集環境部署記錄

1)機器環境
192.168.88.188    master-node(主節點)
192.168.88.189    slave-node1(從節點)
192.168.88.191    slave-node2(從節點)
 
MongoDB 安裝目錄:/usr/local/mongodb
MongoDB 資料庫目錄:/usr/local/mongodb/data
MongoDB 日誌目錄:/usr/local/mongodb/log/mongo.log
MongoDB 配置檔案:/usr/local/mongodb/mongodb.conf
安裝mongodb可以參考前邊的操作
對以上三臺伺服器部署Mongodb的副本集功能,定義副本集名稱為:hqmongodb
關閉三臺伺服器的iptables防火牆和selinux 配置檔案: 三個節點配置檔案一樣,就是ip是各自的ip地址

[root@localhost mongodb]# cat mongodb.conf
port=27017
bind_ip = 192.168.88.188
dbpath=/usr/local/mongodb/data
logpath=/usr/local/mongodb/log/mongo.log
pidfilepath=/usr/local/mongodb/mongo.pid
fork=true
logappend=true
shardsvr=true
directoryperdb=true
#auth=true
#keyFile =/usr/local/mongodb/keyfile
replSet =hqmongodb

啟動指令碼 注意ip地址是各自的IP地址

[root@localhost mongodb]# cat /etc/init.d/mongodb
#!/bin/bash
# chkconfig: - 64 36
# description:mongod
case $1 in
start)
/usr/local/mongodb/bin/mongod --maxConns 20000 --config /usr/local/mongodb/mongodb.conf
;;
stop)
/usr/local/mongodb/bin/mongo 192.168.88.188:27017/admin --eval "db.shutdownServer()"
#/usr/local/mongodb/bin/mongo 182.48.115.236:27017/admin --eval "db.auth('system', '123456');db.shutdownServer()"
;;
status)
/usr/local/mongodb/bin/mongo 192.168.88.188:27017/admin --eval "db.stats()"
#/usr/local/mongodb/bin/mongo 182.48.115.236:27017/admin --eval "db.auth('system', '123456');db.stats()"
;;
esac

啟動 # yum install net-snmp # ulimit -SHn 655350 # /etc/init.d/mongodb start 啟動報錯

[root@localhost data]# /etc/init.d/mongodb start
about to fork child process, waiting until server is ready for connections.
forked process: 2924
ERROR: child process failed, exited with 100
To see additional information in this output, start without the "--fork" option.

解決

# rm -rf /usr/local/mongodb/data/mongod.lock //由於我的測試環境下沒有資料,我將data資料目錄下的檔案全部清空,然後--repair

# /usr/local/mongodb/bin/mongod --repair 檢視:

root@localhost init.d]# ps -ef |grep mongodb
root 24995 1 2 12:19 ? 00:00:18 /usr/local/mongodb/bin/mongod --maxConns 20000 --config /usr/local/mongodb/mongodb.conf
root 25098 2532 0 12:33 pts/0 00:00:00 grep --color=auto mongodb
[root@localhost init.d]# lsof -i:20717

3)對master-node主節點進行配置(192.168.88.188)//其實,剛開始這三個節點中的任何一個都可以用來初始化為開始的主節點。這裡選擇以master-node為主節點

[root@master-node ~]# mongo 192.168.88.188:27017 //登陸到mongodb資料庫中執行下面命令操作。由於配置檔案中綁定了ip,所以要用這個繫結的ip登陸 3.1)初始化副本集,設定本機為主節點 PRIMARY

MongoDB Enterprise > rs.initiate()
{
"info2" : "no configuration specified. Using a default configuration for the set",
"me" : "192.168.88.188:27017",
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1597638981, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1597638981, 1)
}

MongoDB Enterprise hqmongodb:SECONDARY> rs.conf()
{
"_id" : "hqmongodb",
"version" : 1,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "192.168.88.188:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {

},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : -1,
"catchUpTakeoverDelayMillis" : 30000,
"getLastErrorModes" : {

},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5f3a094534edd925892685e9")
}
}

3.2)新增副本集從節點。(發現在執行上面的兩個命令後,字首已經改成"hqmongodb:PRIMARY"了,即已經將其自己設定為主節點 PRIMARY了)

MongoDB Enterprise hqmongodb:PRIMARY> rs.add("192.168.88.189:27017")
{
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1597639227, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1597639227, 1)
}

MongoDB Enterprise hqmongodb:PRIMARY> rs.add("192.168.88.191:27017")
{
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1597639255, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1597639255, 1)
}

3.3)設定節點優先順序

hqmongodb:PRIMARY> cfg = rs.conf()//檢視節點順序

hqmongodb:PRIMARY> cfg.members[0].priority = 1 1 hqmongodb:PRIMARY> cfg.members[1].priority = 1 1 hqmongodb:PRIMARY> cfg.members[2].priority = 2//設定_ID 為 2 的節點為主節點。 2 hqmongodb:PRIMARY> rs.reconfig(cfg)//使配置生效 {"ok": 1 } 說明: MongoDB副本集通過設定priority 決定優先順序,預設優先順序為1,priority值是0到100之間的數字,數字越大優先順序越高,priority=0,則此節點永遠不能成為主節點 primay。 cfg.members[0].priority =1 引數,中括號裡的數字是執行rs.conf()檢視到的節點順序, 第一個節點是0,第二個節點是 1,第三個節點是 2,以此類推。優先順序最高的那個 被設定為主節點。 4)分別對兩臺從節點進行配置 slave-node1節點操作(182.48.115.237) [root@slave-node1 ~]# mongo 182.48.115.237:27017 ..... hqmongodb:SECONDARY> db.getMongo().setSlaveOk()//設定從節點為只讀.注意從節點的字首現在是SECONDARY。看清楚才設定 slave-node2節點操作(182.48.115.238) [root@slave-node2 ~]# mongo 182.48.115.238:27017 ...... hqmongodb:SECONDARY> db.getMongo().setSlaveOk()//從節點的字首是SECONDARY,看清楚才設定。執行這個,否則後續從節點同步資料時會報錯:"errmsg":"not master and slaveOk=false", hqmongodb:PRIMARY> show dbs local0.000GB hqmongodb:PRIMARY> use admin//mongodb3.0沒有admin資料庫了,需要手動建立。admin庫下新增的賬號才是管理員賬號 switched to db admin hqmongodb:PRIMARY> show collections #新增兩個管理員賬號,一個系統管理員:system 一個數據庫管理員:administrator #先新增系統管理員賬號,用來管理使用者 hqmongodb:PRIMARY> db.createUser({user:"system",pwd:"123456",roles:[{role:"root",db:"admin"}]}) #新增資料庫管理員,用來管理所有資料庫 hqmongodb:PRIMARY> db.createUser({user:'administrator',pwd:'123456', roles:[{ role:"userAdminAnyDatabase", db:"admin"}]}); hqmongodb:PRIMARY> db.auth('administrator','123456')//新增管理員使用者認證,認證之後才能管理所有資料庫 1 hqmongodb:PRIMARY> db admin hqmongodb:PRIMARY> show collections system.users system.version 檢視hqmongodb:PRIMARY> db.system.users.find() 退出,用剛才建立的賬號進行登入 [root@master-node ~]# mongo 182.48.115.236:27017 -u system -p 123456 --authenticationDatabase admin [root@master-node ~]# mongo 182.48.115.236:27017 -u administrator -p 123456 --authenticationDatabase admin 5.2)開啟登入驗證 在master-node主節點伺服器182.48.115.236上面操作 [root@master-node ~]# cd /usr/local/mongodb/ //切換到mongodb主目錄 [root@master-node mongodb]# openssl rand -base64 21 > keyfile //建立一個 keyfile(使用 openssl 生成 21 位 base64 加密的字串) [root@master-node mongodb]# chmod 600 /usr/local/mongodb/keyfile [root@master-node mongodb]# cat /usr/local/mongodb/keyfile //檢視剛才生成的字串,做記錄,後面要用到 RavtXslz/WTDwwW2JiNvK4OBVKxU 注意:上面的數字 21,最好是 3 的倍數,否則生成的字串可能含有非法字元,認證失敗。 5.3)設定配置檔案 分別在所有節點上面操作(即三個節點的配置檔案上都要修改) [root@master-node ~]# vim /usr/local/mongodb/mongodb.conf //新增下面兩行內容 ...... auth=true keyFile =/usr/local/mongodb/keyfile 啟動指令碼使用下面的程式碼(註釋原來的,啟用之前註釋掉的) [root@master-node ~]# cat /etc/init.d/mongodb #!/bin/sh # chkconfig: - 64 36 # description:mongod case$1in start) /usr/local/mongodb/bin/mongod--maxConns 20000 --config/usr/local/mongodb/mongodb.conf ;; stop) #/usr/local/mongodb/bin/mongo 182.48.115.236:27017/admin --eval "db.shutdownServer()" /usr/local/mongodb/bin/mongo182.48.115.236:27017/admin--eval"db.auth('system', '123456');db.shutdownServer()" ;; status) #/usr/local/mongodb/bin/mongo 182.48.115.236:27017/admin --eval "db.stats()" /usr/local/mongodb/bin/mongo182.48.115.236:27017/admin--eval"db.auth('system', '123456');db.stats()" ;;esac 5.4)設定許可權驗證檔案 先進入master-node主節點伺服器182.48.115.236,檢視 [root@master-node ~]# cat /usr/local/mongodb/keyfile RavtXslz/WTDwwW2JiNvK4OBVKxU//檢視剛才生成的字串,做記錄 再分別進入兩臺從節點伺服器182.48.115.237/238 [root@slave-node1 ~]# vim /usr/local/mongodb/keyfile //將主節點生成的許可權驗證字元碼複製到從節點的許可權驗證檔案裡 RavtXslz/WTDwwW2JiNvK4OBVKxU [root@slave-node1 ~]# chmod 600 /usr/local/mongodb/keyfile [root@slave-node2 ~]# vim /usr/local/mongodb/keyfile [root@slave-node2 ~]# cat /usr/local/mongodb/keyfile RavtXslz/WTDwwW2JiNvK4OBVKxU [root@slave-node2 ~]# chmod 600 /usr/local/mongodb/keyfile rs.status() 檢視叢集狀態 注意上面命令結果中的state,如果這個值為 1,說明是主控節點(master);如果是2,說明是從屬節點slave。在上面顯示的當前主節點寫入資料,到從節點上檢視發現數據會同步。 當主節點出現故障的時候,在兩個從節點上會選舉出一個新的主節點,故障恢復之後,之前的主節點會變為從節點。從上面叢集狀態中開看出,當前主節點是master-node,那麼關閉它的mongodb,再次檢視叢集狀態,就會發現主節點變為之前設定的slave-node2,即182.48.115.238了! 至此,Linux 下 MongoDB 副本集部署完成。

驗證

新增資料,來需要驗證的--------------------
1)主從伺服器資料是否同步,從伺服器沒有讀寫許可權
a:向主伺服器寫入資料 ok 後臺自動同步到從伺服器,從伺服器有資料
b:向從伺服器寫入資料 false 從伺服器不能寫
c:主伺服器讀取資料 ok
d:從伺服器讀取資料 false 從伺服器不能讀
 
2)關閉主伺服器,從伺服器是否能頂替
 mongo 的命令列執行 rs.status() 發現 PRIMARY 替換了主機了
 
3)關閉的伺服器,再恢復,以及主從切換
 a:直接啟動關閉的服務,rs.status()中會發現,原來掛掉的主伺服器重啟後變成從伺服器了
 b:額外刪除新的伺服器 rs.remove("localhost:9933"); rs.status()
 c:額外增加新的伺服器 rs.add({_id:0,host:"localhost:9933",priority:1});
 d:讓新增的成為主伺服器 rs.stepDown(),注意之前的 priority 投票
 
4)從伺服器讀寫
 db.getMongo().setSlaveOk();
 db.getMongo().slaveOk();//從庫只讀,沒有寫許可權,這個方法 java 裡面不推薦了
 db.setReadPreference(ReadPreference.secondaryPreferred());// 在 復 制 集 中 優 先 讀
 secondary,如果 secondary 訪問不了的時候就從 master 中讀
 db.setReadPreference(ReadPreference.secondary());// 只 從 secondary 中 讀 , 如 果
 secondary 訪問不了的時候就不能進行查詢
日誌檢視---------------------------
MongoDB 的 Replica Set 架構是通過一個日誌來儲存寫操作的,這個日誌就叫做”oplog”, 它存在於”local”資料庫中,oplog 的大小是可以通過 mongod 的引數”—oplogSize”來改變 oplog 的日誌大小。 > uselocal switched to dblocal > db.oplog.rs.find() {"ts": {"t": 1342511269000,"i": 1 },"h": NumberLong(0),"op":"n","ns":"","o": {"msg":"initiating set"} } 欄位說明: ts: 某個操作的時間戳 op: 操作型別,如下: i: insert d: delete u: update ns: 名稱空間,也就是操作的 collection name ------------------------------------------------------------------------------------------- 其它注意細節: rs.remove("ip:port");//刪除副本 單伺服器,啟動時新增--auth 引數開啟驗證。 副本集伺服器,開啟--auth 引數的同時,必須指定 keyfile 引數,節點之間的通訊基於該 keyfile,key 長度必須在 6 到 1024 個字元之間, 最好為 3 的倍數,不能含有非法字元。 重新設定副本集 rs.stepDown() cfg = rs.conf() cfg.members[n].host='new_host_name:prot' rs.reconfig(cfg) 副本集所有節點伺服器總數必須為奇數,伺服器數量為偶數的時候,需要新增一個仲裁節 點,仲裁節點不參與數副本集,只有選舉權。 rs.addArb("182.48.115.239:27017")#新增仲裁節點