副本集 可以將MongoDB中的副本集看作一組伺服器集群由一個主節點和多個副本節點等組成,相對於之前講到的主從複製提供了故障自動轉移的功能 副本集實現數據同步的方式依賴於local資料庫中的oplog數據 oplog是存在與主節點或副本節點上的local資料庫中的一個固定集合,記錄了每一次主節點的寫... ...
副本集
可以將MongoDB中的副本集看作一組伺服器集群由一個主節點和多個副本節點等組成,相對於之前講到的主從複製提供了故障自動轉移的功能
副本集實現數據同步的方式依賴於local資料庫中的oplog數據
- oplog是存在與主節點或副本節點上的local資料庫中的一個固定集合,記錄了每一次主節點的寫操作,或副本節點每一次從主節點複製數據的操作
- 備份節點通過定時從主節點獲取oplog數據,併在本機執行這些操作來實現主從複製的功能,同樣的每個副本節點也可以作為數據源給其他成員使用
- 備份節點在本機上執行完從主節點獲取到的oplog數據後,會在自己的local資料庫中記錄這些的操作
- 如果某個副本節點由於某些原因宕機了,當重啟後會從oplog中最後一個操作開始進行同步,由於複製過程是先進行複製再寫入本機oplog的,所以副本節點可能會在已經同步過的數據上再次執行複製操作,不過oplog中的統一操作執行多次與執行一次效果是一樣的
oplog欄位說明
- ts:執行某個操作的時間戳
- op:操作類型(i-insert;d-delete;u-update)
- ns:操作的集合的名稱
- o:document的內容
副本集中的各種角色
- 主節點——有且只有一個,預設處理了所有的客戶端請求(讀和寫)
- 副本節點——可以有多個,保存主節點的副本數據,當主節點出問題時可以通過投票升級為主節點,可以處理客戶端的只讀請求
- 仲裁節點——不進行數據複製存儲,也不為客戶端提供服務,唯一的作用是進行故障轉移時的投票,選舉出新的主節點 仲裁節點一旦被設置則永遠不能成為非仲裁節點,反之一樣 一個副本集集群中最多只能有一個仲裁節點,如果節點總數為基數時就不需要配置仲裁節點了,因為仲裁節點的作用就是在節點總數為偶數時,如果一半投票給A,一半頭片給B這時仲裁節點就持有關鍵性的一票 如果有可能儘量使用奇數的集群節點,不要使用仲裁節點
- 隱藏節點——不為客戶端提供服務,永遠不會成為主節點但是會參與投票,進行數據的複製存儲,一般用作數據備份 如果要設置一個節點為隱藏設置其hidden屬性為true即可 只有優先順序priority=0的節點才能被設置為隱藏
- 延遲同步節點——一般會人為設置一個延遲時間(單位秒)來從主節點同步數據,主要就是用於數據的備份,當資料庫發生毀滅性災難時進行數據恢復 延遲同步節點的優先順序priority=0並且是隱藏節點,避免讀請求被路由到延遲同步節點上 通過屬性slaveDelay(單位秒)來設置一個節點的延遲同步時間
- Secondary-Only——通常將性能不高的節點設置為此類型,防止其成為主節點,優先順序priority=0
- Non-Voting——沒有投票權的副本節點,純粹用於數據備份,一般只有當節點總數超過12個時才會被使用,通過votes=0設置其為Non-Voting節點
部署副本集
創建主從key文件,用於表示集群私鑰的完整路徑,如果各個實例的密鑰不一致則程式不能正常使用
openssl rand -base64 100 > key
創建資料庫目錄及日誌目錄並修改其配置文件
//replica set 0
systemLog:
path: D:\mongodb\replicaSet\rs0\logs\mongodb.log
logAppend: true
destination: file
storage:
dbPath: D:\mongodb\replicaSet\rs0\data
net:
port: 27017
bindIp: 127.0.0.1
security:
keyFile: D:\mongodb\replicaSet\rs0\key
replication:
replSetName: replcaSetTest
secondaryIndexPrefetch: all
//relica set 1
systemLog:
path: D:\mongodb\replicaSet\rs1\logs\mongodb.log
logAppend: true
destination: file
storage:
dbPath: D:\mongodb\replicaSet\rs1\data
net:
port: 27018
bindIp: 127.0.0.1
security:
keyFile: D:\mongodb\replicaSet\rs1\key
replication:
replSetName: replcaSetTest
secondaryIndexPrefetch: all
//relica set 2
systemLog:
path: D:\mongodb\replicaSet\rs2\logs\mongodb.log
logAppend: true
destination: file
storage:
dbPath: D:\mongodb\replicaSet\rs2\data
net:
port: 27019
bindIp: 127.0.0.1
security:
keyFile: D:\mongodb\replicaSet\rs2\key
replication:
replSetName: replcaSetTest
secondaryIndexPrefetch: all
啟動以上三個實例
mongod -config D:\mongodb\replicaSet\rs0\mongodb.conf
mongod -config D:\mongodb\replicaSet\rs1\mongodb.conf
mongod -config D:\mongodb\replicaSet\rs2\mongodb.conf
配置及初始化副本集
rsConfig = {
_id: "replcaSetTest",
members: [{ _id: 0, host: "127.0.0.1:27017" },
{ _id: 1, host: "127.0.0.1:27018" },
{ _id: 2, host: "127.0.0.1:27019" }
]
};
rs.initiate(rsConfig);
_id就是啟動MongoDB實例時設置的副本集名稱,一定要保障兩處副本集名稱一致 members副本集成員數組,一個唯一的數值類型的_id,一個主機名 rs.initiate()函數用來初始化副本集
輸入rs.config()查詢配置修改是否成功,竟然提示沒有許可權
rs.config()
2016-11-23T17:18:00.689+0800 E QUERY [thread1] Error: Could not retrieve replica set config: {
"ok" : 0,
"errmsg" : "not authorized on admin to execute command { replSetGetConfig: 1.0 }",
"code" : 13
}
執行以下名稱創建創建管理員賬戶,並授予許可權,創建成功後執行db.auth() 命令進行登錄授權
db.createUser({
user: 'admin',
pwd: 'mongodb_123',
roles: [{ "role": "clusterAdmin", "db": "admin" },
{ "role": "userAdminAnyDatabase", "db": "admin" },
{ "role": "dbAdminAnyDatabase", "db": "admin" },
{ role: "root", db: "admin" }
]
})
db.auth("admin","mongodb_123")
再次執行rs.config()得到以下信息
rs.config()
{
"_id" : "replcaSetTest",
"version" : 1,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "127.0.0.1:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "127.0.0.1:27018",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "127.0.0.1:27019",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5835597e61b9c2f7c562b9b0")
}
}
version 在每次修改副本集配置時都會遞增,初始值為1 rs.starus()或rs.isMaster() 指令可以查詢當前副本集的狀態
local資料庫中不僅有oplog日誌集合,還有一個用於記錄主從配置信息的集——system.replset 通過這個集合可以查看副本集的配置信息當然在每個實例上執行rs.config()或rs.conf()也能達到同樣的效果
db.system.replset.find()
在主節點上創建測試數據
use myReplSetTest
for (i = 5000; i < 100000; i++) {
db.users.insert({
"i": i,
"userName": "user" + i,
"age": Math.floor(Math.random() * 120),
"created": new Date(),
total: Math.floor(Math.random() * 100) * i
})
}
db.users.find()
在主節點上執行查詢OK,但是當在副本節點進行執行是則報錯,提示不是主節點並且slaveOk=false不能執行查詢操作
QUERY [thread1] Error: listCollections failed: { "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 }
在副本節點中執行名稱db.setSlaveOk()讓副本節點可以讀取數據,分單主庫壓力達到讀寫分離的效果,再次執行db.users.find()就正常了
副本集管理
rs.add()可以添加節點 添加節點的方式有兩種: 1.通過oplog直接添加,這種方式添加節點過程中不需要過多的人工干預就可以完成,但是如果頻繁的插入修改等操作會導致oplog數據較大,在進行複製時會使源節點的壓力較大 並且oplog是固定集合,因為他的特性可能會導致複製的數據不一致 2.通過資料庫快照(--fastsync)獲取某一個副本節點的物理文件來做初始化數據,剩餘的部分通過oplog日誌進行追加可以解決上述的問題,
通過方式1來新增節點,方式同創建mongodb副本集(創建對應的數據文件夾,修改配置文件,啟動mongodb實例)
systemLog:
path: D:\mongodb\replicaSet\rs3\logs\mongodb.log
logAppend: true
destination: file
storage:
dbPath: D:\mongodb\replicaSet\rs3\data
net:
port: 27020
bindIp: 127.0.0.1
security:
keyFile: D:\mongodb\replicaSet\rs3\key
replication:
replSetName: replcaSetTest
secondaryIndexPrefetch: all
mongod -config D:\mongodb\replicaSet\rs3\mongodb.conf
//主節點中執行
rs.add("127.0.0.1:27020");
使用方式2 進行節點新增 1.複製rs3中文件至文件夾rs4 2.修改配置文件如下: 3.啟動新的mongodb實例
systemLog:
path: D:\mongodb\replicaSet\rs4\logs\mongodb.log
logAppend: true
destination: file
storage:
dbPath: D:\mongodb\replicaSet\rs4\data
net:
port: 27021
bindIp: 127.0.0.1
security:
keyFile: D:\mongodb\replicaSet\rs4\key
replication:
replSetName: replcaSetTest
secondaryIndexPrefetch: all
mongod -config D:\mongodb\replicaSet\rs3\mongodb.conf
//主節點中添加測試數據
db.usertest.insert({name:1})
//主節點中執行
rs.add("127.0.0.1:27021");
//新添加的副本節點中執行show collections 發現已經同步
rs.remove()可以進行節點移除
rs.remove("127.0.0.1:27020");
rs.reconfig()可以修改副本集配置,特別是針對複雜的副本集配置,比rs.add()和rs.remove()更有效
config = rs.config();
config.members[1].priority = 20;
rs.reconfig(config);
以上命令修改了 127.0.0.1:27018的優先順序,發現修改完成後自動切換為了主節點,通過命令rs.status()可以查看
副本集監控
主節點中執行 db.printReplicationInfo() 命令可以查看oplog信息
- configured oplog size——配置的oplog文件大小
- log length start to end——oplog日誌的啟用時間段
- oplog first event time——第一個事務日誌產生的時間
- oplog last event time——最後一個事務日誌產生的時間
- now——當前時間
副本節點中執行db.printSlaveReplicationInfo()命令可以查看同步狀態信息
- source——從庫的IP及埠
- syncedTo——當前的同步情況,,延遲了多久等信息