mongodb 复制集
2022-08-30
复制集的一些注意事项
复制集的作用
MongoDB 复制集的主要意义在于实观服务高可用,它的现实依赖于两个方面的功能:
数据写入时将数据迅速复制到另一个独立节点上
在接受写入的节点发生故障时自动选举出一个新的替代节点
在实现高可用的同时,复制集实现了其他几个附加作用:
数据分发:将数据从一个区域复制到另一个区域,减少另一个区域的读延迟
读写分离:不同类型的压力分别在不同的节点上执行
异地容灾:在数据中心故障时候快速切换到异地
复制集结构
PSS:一主两从 生产环境中,pss居多,psa 会有一些弊端;
PAS:一主一从 一个投票节点
一个典型的复制集由 3 个以上具有投票权的节点组成,
包括:
一个主节点(PRIMARY):接受写入操作和选举时投票
两个(或多个)从节点(SECONDARY):复制主节点上的新数据和选举时投票
Arbiter(投票节点)
数据是如何复制的
当一个修改操作,无论是插入、更新或删除,到达主节点时,它对数据的操作将被记录下来(经过一些必要的转换),这些记录称为 oplog.
从节点通过在主节点上打开一个 tailable 游标不断获取新进入主节点的 oplog,并在自己的数据上回放,以此保持跟主节点的数据一致。
通过选举完成故障转移
具有投票权的节点之间两两互相发送心跳;
当 5 次心跳未收到时判断为节点失联;
如果失联的是主节点,从节点会发起选举,选出新的主节点;
如果失联的是从节点则不会产生新的选举;
选举基于 RAFT 一致性算法实现,选举成功的必要条件是大多数投票节点存活;
影响选举的因素
整个集群必须有大多数节点存活;被选举为主节点的节点必须:
·能够与多数节点建立连接
·具有较新的 oplog
·具有较高的优先级(如果有配置)
常见选项
复制集节点有以下常见的选配项:
·是否具有投票权(v 参数):有则参与投票;
·优先级(priority 参数):优先级越高的节点越优先成为主节点。优先级为 0 的节点无法成为主节点;
·隐藏(hidden 参数):复制数据,但对应用不可见。隐藏节点可以具有投票仅,但优先级必须为 O;
·延迟(slaveDelay 参数):复制 n 秒之前的数据,保持与主节点的时间差。
复制集注意事项
·关于硬件:
·因为正常的复制集节点都有可能成为主节点,它们的地位是一样的,因此硬件配置上必须一致;
·为了保证节点不会同时宿机,各节点使用的硬件必须具有独立性。
·关于软件:
·复制集各节点软件版本必须一致,以避免出现不可预知的问题。
·增加节点不会增加系统写性能!
默认从节点没有读权限,如果修改为了读权限,默认是强制读,没有写权限;
一旦作为一个节点的从库,就不可以再作为另外一个节点的从库;
复制集配置
a.规划
三个以上节点或者多实例
多实例:
1.多个端口:28017、28018、28019、28020
2.多套目录
su - mongod
mkdir -p /mongodb/{28017..28020}/{data,log}
3.配置文件
# https://raw.githubusercontent.com/mongodb/mongo/3a848e239082625f1f1e6c677f149412654f53b6/rpm/mongod.conf
cat > /mongodb/28017/mongod.conf <<EOF
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /mongodb/28017/log/mongodb.log
# Where and how to store data.
storage:
journal:
enabled: true
dbPath: /mongodb/28017/data
directoryPerDB: true
#engine: wiredTiger
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
# how the process runs
processManagement:
fork: true # fork and run in background
timeZoneInfo: /usr/share/zoneinfo
# network interfaces
net:
port: 28017
bindIp: 127.0.0.1,10.23.5.242 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
#security:
#operationProfiling:
replication:
oplogSizeMB: 2048
replSetName: my_rep
#sharding:
## Enterprise-Only Options
#auditLog:
EOF
cp /mongodb/28017/mongod.conf /mongodb/28018/
cp /mongodb/28017/mongod.conf /mongodb/28019/
cp /mongodb/28017/mongod.conf /mongodb/28020/
sed -i 's#28017#28018#g' /mongodb/28018/mongod.conf
sed -i 's#28017#28019#g' /mongodb/28019/mongod.conf
sed -i 's#28017#28020#g' /mongodb/28020/mongod.conf
# 启动实例
mongod -f /mongodb/28017/mongod.conf
mongod -f /mongodb/28018/mongod.conf
mongod -f /mongodb/28019/mongod.conf
mongod -f /mongodb/28020/mongod.conf
b. 配置复制集
1. 1主2从,从库是普通从库(PSS)
config = {_id: "my_rep", members: [
{_id: 0, host: '10.23.5.242:28017'},
{_id: 1, host: '10.23.5.242:28018'},
{_id: 2, host: '10.23.5.242:28019'}
]}
rs.initiate(config)
2. 1主1从1个arbiter(PSA)
config = {_id: "my_rep", members: [
{_id: 0, host: '10.23.5.242:28017'},
{_id: 1, host: '10.23.5.242:28018'},
{_id: 2, host: '10.23.5.242:28019', "arbiterOnly": true}
]}
rs.initiate(config)
c. 复制测试
my_rep:PRIMARY> db.movies.insert([ {"title": "Jaws", "year": 1975, "imdb_rating": 8.1},
... {"title": "batman", "year": 1985, "imdb_rating": 7.6 },
... ]);
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
// 从库配置读功能;默认mongodb从库没有读功能;
my_rep:SECONDARY> rs.slaveOk()
// 查看插入的数据
my_rep:SECONDARY> db.movies.find()
{ "_id" : ObjectId("630d774f7eca224e1f888695"), "title" : "batman", "year" : 1985, "imdb_rating" : 7.6 }
{ "_id" : ObjectId("630d774f7eca224e1f888694"), "title" : "Jaws", "year" : 1975, "imdb_rating" : 8.1 }
d. 查看复制集状态
// 可以打印当前复制集状态信息;
my_rep:PRIMARY> rs.status()
// 重点看 members
"members" : [
{
"_id" : 0,
"name" : "10.23.5.242:28017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 956,
"optime" : { // 日志的版本号
"ts" : Timestamp(1661827202, 1), // 使用ts 的方式记录;1661827202 当前时间戳、1代表在时间戳的这一秒中的第几个操作;
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-08-30T02:40:02Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1661826682, 1),
"electionDate" : ISODate("2022-08-30T02:31:22Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
....
rs.isMaster() // 查看是否是主节点
2. 添加删除节点
rs.add("ip:port"); // 新增从节点
rs.addArb("ip:port"); // 新增仲裁节点
rs.remove("ip:port"); // 删除一个节点
3. 特殊从节点的配置
- 优先级(priority 参数:0-100)
优先级越高的从节点越优先成为主节点;
优先级为0的节点无法成为主节点;
- 隐藏(hidden参数):复制数据,但对应用不可见。隐藏节点可以具有投票权,但优先级必须为0;
- 延迟(slaveDelay参数):复制n秒之前的数据,保持与主节点的时间差。
配置延迟节点(一般延迟节点也配置成 hidden)
cfg=rs.conf() // 将 rs.conf() 导入到变量 cfg中
cfg.members[1].priority=0 // 修改其中的字段 priority ,将其改为0;优先级;members[1] 列表索引,代表具体节点;列表索引从 0 开始,依次往后排,
cfg.members[1].slaveDelay=120 // 修改字段 slaveDelay ,将其改为 120;与主节点时间差,延迟复制
cfg.members[1].hidden=true // 修改字段 hidden ,将其改为 true;是否隐藏
cfg.members[1].votes=0
rs.reconfig(cfg) // 重新配置
改回来:
cfg=rs.conf()
cfg.members[2].priority=1
cfg.members[2].slaveDelay=0
cfg.members[2].hidden=0
cfg.members[2].votes=0
rs.reconfig(cfg)
配置成功后,通过以下命令查询配置后的属性
rs.conf();
e.副本集其他操作命令
-查看副本集的配置信息
admin> rs.config()
-查看副本集各成员的状态
admin> rs.status()
-一副本集角色切换(不要人为顺便操作,有风险)
admin> rs.stepDown()
注:
admin> rs.freeze(300) //锁定从,使其不会转变成主库; 主从切换时可以使用;锁定该从,使其切换到别的从库
freeze() 和 stepDown 单位都是秒。
-一设置副本节点可读:在副本节点执行
admin> rs.slaveok()
eg:
admin> use app
app> db.createCollection('a')
--查看副本节点信息
admin> rs.printSlaveReplicationInfo()
source:192.168.1.22:27017
syncedTo: Thu May 26 2016 10: 28: 56 GMT+0800 (CST)
0 secs (o hrs) behind the primary // 这是延时信息;