mongodb 集群搭建 副本集
下载mongodb:
下载地址:https://www.mongodb.com/download-center#community
到这个地址中选着linux版本,然后选择 “RHEL 7 Linux 64-bit x64”然后下面就会出现下载按钮,或使用右边的下载地址。
下载安装:
wget 下载:
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.1.tgz
手动安装:
tar xf mongodb-linux-x86_64-rhel70-4.0.1.tgz mv mongodb-linux-x86_64-rhel70-4.0.1 /usr/local/mongodb mkdir /usr/local/mongodb/{conf,logs,db} -pv
使用yum安装:
创建yum源:
官网yum源:https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
阿里云yum源:https://mirrors.aliyun.com/mongodb/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
vim mongodb-org-3.4.repo [mongodb-org-3.4] name=MongoDB 3.4 Repository baseurl=https://mirrors.aliyun.com/mongodb/yum/redhat/$releasever/mongodb-org/3.4/x86_64/ gpgcheck=0 enabled=1
安装:
yum install mongodb-org
会自动安装如下几个包:
mongodb-org-mongos
mongodb-org-server
mongodb-org-shell
mongodb-org-tools
配置:
一些常用配置项:
dbpath:数据目录
logpath:日志目录
port:端口
fork:true 表示后台运行
集群复制的关键两个选项:
Replica set options:
--replSet arg 副本集的名称,决定了当前副本集加入的是哪一个集群
--replIndexPrefetch arg 副本集的索引预取,可以让复制更高效,[ none 不预取 | _id_only 预取id | all 预取所有 ],这个操作只能定义在从节点上,定义在主节点上是没有意义的。加上这一项说明当前节点作为副本集成员启动的。(其实这个不设置也行)。
复制集群搭建
mongo版本3.4,最好用rpm包安装,因为有写好的配置文件如果没有则使用如下的配置文件。rpm安装的mongo默认配置文件在 /etc/mongod.conf 中,内容如下,3.4版本的配置文件使用的是类json格式。
# mongod.conf # 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: /var/log/mongodb/mongod.log # Where and how to store data. storage: dbPath: /var/lib/mongo journal: enabled: true # engine: # mmapv1: # wiredTiger: # how the process runs processManagement: fork: true # fork and run in background pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile # network interfaces net: port: 27017 bindIp: 0.0.0.0 # Listen to local interface only, comment to listen on all interfaces. #security: #operationProfiling: replication: replSetName: spock #sharding: ## Enterprise-Only Options #auditLog: #snmp:
主要设置了两个地方,第一个是复制集的名称,相同复制集名称要相同。也就是说当前配置的复制集都要用同一个名称。
replication: replSetName: spock
第二个是bindIp 这个是用来控制访问的。
bindIp: 0.0.0.0
开始搭建:
准备三台机器,分别安装上mongo,只有主节点可以有数据,其他节点如果有数据的话把数据目录下的内容删除即可,否者会报错。
启动mongo:
因为当前用的是rpm安装的,所以直接使用systemctl start mongod.service 来启动就可以了,配置文件已经在mongod.service 文件中指定过了。如果是手动安装的mongod命令需要用 mongod -f configFilePath 来指定配置文件。
先在有数据的节点上准备如下配置:
config = { "_id":"spock", "members":[ {"_id":0, "host":"192.168.1.113:27017"}, {"_id":1, "host":"192.168.1.114:27017"}, {"_id":2, "host":"192.168.1.115:27017"} ] }
上面config中的 "_id": "spock" 这个值就是配置文件中 replSetName: spock 这一项的值。
然后运行初始化命令:
rs.initiate(config)
如果返回中有 ok : 1 则说明集群创建成功。使用下面命令可以查看集群状态:
rs.status()
在输出的信息中 "stateStr" : "PRIMARY" 表示主节点,可以进行写操作,其他的只能执行查询操作。
一些副本集的设置
添加或移除成员:
移除成员:
rs.add("192.168.1.115:27017")
添加成员:
rs.add("192.168.1.115:27017")
添加或移除成员后可以使用 rs.isMaster() 或 rs.status() 或 rs.config() 查看是否被添加或移除了。
修改某成员信息:
var config = rs.config() config.members[1].host = "mongodb02:27017" rs.reconfig(config)
设置成员优先级:
让某个成员成为主节点,只要这个节点的数据足够新就会成为主节点。
rs.add({"_id":1,"host":"192.168.1.114:27017","priority":1.5})
添加仲裁者到副本集:
rs.addArb("mongodb04:27017")
或:
rs.add({"_id":4, "host":"mongodb04:27017","arbiterOnly":true})
隐藏成员:
如果是隐藏成员是不会通过rs.isMaster() 查看到的,隐藏成员对用户不可见,不可查询。
spock:SECONDARY> rs.isMaster() { "hosts" : [ "192.168.1.113:27017", "192.168.1.114:27017", "192.168.1.115:27017" ], ... }
在主节点上操作如下:其中members[2] 这个2表示hosts中按顺序数第三个主机。
spock:PRIMARY> var config = rs.config() spock:PRIMARY> config.members[2].hidden = 0 0 spock:PRIMARY> config.members[2].priority = 0 0 spock:PRIMARY> rs.reconfig(config) { "ok" : 1 }
这样再执行 rs.isMaster() 命令就可以看到第三个节点被隐藏了。
spock:PRIMARY> rs.isMaster() { "hosts" : [ "192.168.1.113:27017", "192.168.1.114:27017" ], "passives" : [ "192.168.1.115:27017" ], ... }
取消隐藏节点:只要将修改的值改回去就可以了。
spock:PRIMARY> var config = rs.config() spock:PRIMARY> config.members[2].hidden = false false spock:PRIMARY> config.members[2].priority = 1 1 spock:PRIMARY> rs.reconfig(config) { "ok" : 1 }
再次使用 rs.isMaster() 就可以看到被隐藏的节点已近恢复了。
复制延迟:
使用复制延迟优先级必须为0
spock:PRIMARY> var config = rs.config() spock:PRIMARY> config.members[2].slaveDelay = 10 10 spock:PRIMARY> config.members[2].priority = 0 0 spock:PRIMARY> rs.reconfig(config)
改回来就把 priority 改为1 salveDelay 改为0 即可。
指定不创建索引:
有些节点不需要创建索引,看可以设置 "buildIndexes" : false ,注意,这是一个不可逆的设置,除非移除集群删除数据再重新加入。同时也要求优先级必须为0。
var config = rs.config() config.members[2].buildIndexes = false config.members[2].priority = 0 rs.reconfig(config)
把主节点变为备份节点:
rs.stepDown() rs.stepDown(600) #单位秒
这个命令是将主节点退化为备份节点,默认时间60秒,60秒后仍然没有主节点这个节点会重新要求选举,这个时间是可以在括号内设置的。
保持备份节点:
rs.freeze(10000)
这个命令在备份节点上运行可以让备份节点始终保持备份状态,在主节点上运行 rs.freeze(0) 可让退位的主节点重新变为主节点。
使用维护模式:
function maybeMaintenanceMode(){ var local=db.getSisterDB("local"); // 如果成员不是备份节点或处于维护状态就直接返回 if (!local.isMaster().secondary){ return; ) // 查找这个成员最后一次操作的时间 var last=local.oplog.rs.find().sort({"$natural":-1}).next(); var lasttime=last['ts']['t']; // 如果落后30秒以上 if (lasttime<(new date()).getTime()-30){ db.adminCommand({"replSetMaintenanceMode":true}); } };
将成员从维护模式中恢复:
db.adminCommand({"replSetMaintenanceMode":false});
查看当前成员是从哪个成员进行复制的:
hostname.adminCommand({replSetGetStatus:1})['syncingTo']
指定成员的复制源:
hostname.adminCommand({replSetSyncFrom:"192.168.1.114:27017"})
这个修改过程可能需要几分钟。
禁用复制链:
var config = rs.config() // 对象不存在就创建一个空的 config.settings = config.settings || {} config.settings.allowChaining = false rs.reconfig(config)
当 allowChaning 设置为 false 时,所有成员都会从主节点复制数据,当主节点不可用时就会到其他备份节点复制数据。
查看复制这条及延迟:
主节点上:
db.printReplicationInfo()
备份节点上:
db.printSlaveReplicationInfo()
输出的时间为落后时间,只是日志中操作的相差时间,并不表示追赶主节点所要的时间。
调整oplog大小:
如果在oplog记录的时间内备份节点没有恢复,就会导致不得不重新进行完全同步。oplog无法动态修改,可以将备份节点一一下线,修改oplog大小然后上线。
修改oplog的方式为:将当前主机以单机方式启动,把oplog最后一条insert操作保存到其他集合中,然后删除当前的oplog,再创建一个新的oplog,再将最后那条insert操作写回oplog。如果插入没成功就会重新一次完整同步。最后将当前服务器作为副本集启动。
操作方法:
1、如果是主节点,则先将primary 降为 secondary。最后确保没有其他secondary 从该节点复制数据。使用 rs.status() 查看,关闭该mongod服务
use admin db.adminCommand({shutdownServer:1});
2、以单机方式重启该mongod(注释掉 配置文件中的 replSet shardsvr ,修改端口号)
3、将local.oplog.rs中的最后一条 insert 操作记录保存到临时集合中
mongo> use local mongo>var cursor=db.oplog.rs.find({"op":"i"}); mongo>var lastinsert=cursor.sort({$natural:-1}).limit(1).next(); mongo>db.templastop.save(lastinsert); mongo>db.templastop.findOne() #确保写入
4、将oplog.rs 删除:
db.oplog.rs.drop()
5、创建一个新的oplog.rs集合:
db.createCollection("oplog.rs":{"capped":true,"size":10240})
6、将临时集合中的最后一条insert操作记录写回新创建的oplog.rs:
var temp=db.templastop.findOne(); db.oplog.rs.insert(temp); db.oplog.rs.findOne()#确保写回,否则 该节点重新加入副本集后会删除该节点上所有数据,然后重新同步所有数据。
7、最后将该节点以副本集成员的身份重新启动即可。
从延迟备份中恢复:
方法一:
清空非延迟节点上的所有数据,让程序自己从延迟节点去复制数据。
方法二:
把非延迟节点上的数据都删掉,把延迟节点上的数据拷贝到其他成员。
创建索引:
创建索引非常消耗时间,可以将成员一个一个以单机方式启动创建完成索引后再加入副本集,在主节点上趁主节点空闲期将读请求发送到其他节点,然后创建索引,这样所有节点都创建索引成功。或将主节点将为备节点然后在主节点上创建索引,再加入副本集。
查看延迟:
db.slave.find() db.me.findOne() #查看成员标识符
记录着从当前成员同步的成员。
关闭mongo
关闭单机mongo:
方法一:
use admin db.shutdownServer()
方法二:
mongod --shutdown
方法三:
kill <mongod process ID> kill -2 <mongod process ID>
注意:千万不要用 kill -9 ,数据会丢失。
关闭副本集:
如果没有备份节点时强制关闭主节点命令:
db.adminCommand({shutdown : 1, force : true})
关闭备用节点命令,5秒后关闭:
db.adminCommand({shutdown : 1, timeoutSecs : 5})
或:
db.shutdownServer({timeoutSecs : 5})
关闭mongo详见:https://docs.mongodb.com/manual/tutorial/manage-mongodb-processes/