本文共 10540 字,大约阅读时间需要 35 分钟。
CentOS6平台安装MongoDB3.2副本集
一,3台机器全部安装部署mongod
1,下载安装包,并解压tgz
curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.2.10.tgz
tar xf mongodb-linux-x86_64-3.2.10.tgz
mv mongodb-linux-x86_64-3.2.10 /usr/local/mongodb
2,,可执行文件添加到 PATH 路径中:
export PATH=/usr/local/mongodb/bin:$PATH
echo 'export PATH=/usr/local/mongodb/bin:$PATH' > /etc/profile.d/mongodb.sh
3,关闭大页面内存
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
echo "if test -f /sys/kernel/mm/transparent_hugepage/enabled;then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag;then
echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi" >> /etc/rc.d/rc.local
4,限制
ulimit -f unlimited
ulimit -t unlimited
ulimit -v unlimited
ulimit -n 64000
ulimit -m unlimited
ulimit -u 64000
5,创建数据库目录
mkdir -p /data0/mongodb/shardA/data
mkdir -p /data0/logs/mongodb/
6,运行MongoDB服务
(1)编写配置文件
cat /data0/mongodb/shardA/mongo27017.conf
#mongodb shardA 27017
replSet=shardA
dbpath=/data0/mongodb/shardA/data
logpath=/data0/logs/mongodb/27017.log
#bind=192.168.9.168,127.0.0.1
port=27017
fork=true
maxConns=20000
logappend=true
smallfiles=true
(2)启动
/usr/local/mongodb/bin/mongod -f /data0/mongodb/shardA/mongo27017.conf
#其他方式启动
命令行指定dbpath和port
/usr/local/mongodb/bin/mongod --dbpath=/data0/mongodb/shardA --port 27017 &# 默认端口为27017
命令行指定dbpath和port,并启动web界面
/usr/local/mongodb/bin/mongod --dbpath=/data0/mongodb/shardA --port 27017 --rest & #web默认端口为28017
7,查看是否启动正常
netstat -lnptu | grep 27017
ps auxf | grep mongod | grep -v grep
MongoDB后台管理shell
/usr/local/mongodb/bin/mongo 127.0.0.1:27017/test
/usr/local/mongodb/bin/mongo --port 27017
二,配置副本集
1,#连接一台mongo
# /usr/local/mongodb/bin/mongo 192.168.9.168:27017
MongoDB shell version: 3.2.10
2,# 配置168为主,176为从,225为仲裁节点,priority最大为主节点,arbiterOnly仅作为仲裁
> cfg={_id:"shardA", members:[{_id:0,host:'192.168.9.168:27017',priority:2},{_id:1,host:'192.168.9.176:27017',priority:1},{_id:2,host:'192.168.9.225:27017',arbiterOnly:true}]};
{
"_id" : "shardA",
"members" : [
{
"_id" : 0,
"host" : "192.168.9.168:27017",
"priority" : 2
},
{
"_id" : 1,
"host" : "192.168.9.176:27017",
"priority" : 1
},
{
"_id" : 2,
"host" : "192.168.9.225:27017",
"arbiterOnly" : true
}
]
}
# 初始化
> rs.initiate(cfg)
{ "ok" : 1 }
# 也可以手动添加
> rs.initiate()
> rs.add("192.168.9.176:27017")
> rs.add("192.168.9.225:27017",{arbiterOnly:true})
{ "ok" : 1 }
# 删除节点
> rs.remove()
3,查看状态
#查看配置内容
> rs.conf()
#查看状态信息
> rs.status()
#查看是否为主节点
> db.isMaster()
4,主节点插入数据
mongo 192.168.9.176:27017
> show dbs
> use Atest
> for (i=0;i<=1000;i++) db.coltest.insert({count:i})
> show tables
> db.coltest.count()
> db.coltest.find()
mongo 192.168.9.168:27017
> rs.slaveOk()
> show dbs
> show tables
> db.coltest.count()
> db.coltest.find()
shardA:SECONDARY> db.coltest.insert({"count":"10003"})
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })
三,故障转移测试
1,关闭主节点
mongo 192.168.9.176:27017
shardA:PRIMARY> use admin
switched to db admin
shardA:PRIMARY> db.shutdownServer()
server should be down...
2017-11-30T14:13:23.223+0800 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2017-11-30T14:13:24.116+0800 I NETWORK [thread1] Socket recv() errno:104 Connection reset by peer 127.0.0.1:27017
2017-11-30T14:13:24.116+0800 I NETWORK [thread1] SocketException: remote: (NONE):0 error: 9001 socket exception [RECV_ERROR] server [127.0.0.1:27017]
2017-11-30T14:13:24.116+0800 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) failed failed
2017-11-30T14:13:24.118+0800 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2017-11-30T14:13:24.118+0800 W NETWORK [thread1] Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
2017-11-30T14:13:24.118+0800 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) failed failed
>
2,查看备用节点会成为主节点
shardA:SECONDARY>
shardA:PRIMARY> rs.status()
{
"set" : "shardA",
"date" : ISODate("2017-11-30T06:13:57.404Z"),
"myState" : 1,
"term" : NumberLong(3),
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 0,
"name" : "192.168.9.168:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 74322,
"optime" : {
"ts" : Timestamp(1512022413, 1),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2017-11-30T06:13:33Z"),
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1512022412, 1),
"electionDate" : ISODate("2017-11-30T06:13:32Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "192.168.9.176:27017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2017-11-30T06:13:56.562Z"),
"lastHeartbeatRecv" : ISODate("2017-11-30T06:13:21.617Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "Connection refused",
"configVersion" : -1
},
{
"_id" : 2,
"name" : "192.168.9.225:27017",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 70496,
"lastHeartbeat" : ISODate("2017-11-30T06:13:56.543Z"),
"lastHeartbeatRecv" : ISODate("2017-11-30T06:13:52.776Z"),
"pingMs" : NumberLong(0),
"configVersion" : 1
}
],
"ok" : 1
}
shardA:PRIMARY>
3,重新启动原主节点,现主节点还会切过去
shardA:SECONDARY> db.isMaster()
{
"hosts" : [
"192.168.9.168:27017",
"192.168.9.176:27017"
],
"arbiters" : [
"192.168.9.225:27017"
],
"setName" : "shardA",
"setVersion" : 1,
"ismaster" : false,
"secondary" : true,
"primary" : "192.168.9.176:27017",
"me" : "192.168.9.168:27017",
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 1000,
"localTime" : ISODate("2017-11-30T06:20:47.355Z"),
"maxWireVersion" : 4,
"minWireVersion" : 0,
"ok" : 1
}
4,关闭副本集
五,维护相关
1,先关闭从节点、仲裁节点。或者先关闭仲裁节点,最后关闭从节点。则:主节点自动变为从节点
2,先关闭主节点,则从节点自动变为主节点,在仲裁节点关闭之前,新主节点不能关闭
初始化的时候主备节点受priority的影响
priority: 是优先级,默认为1,优先级0为被动节点,不能成为活跃节点。优先级不为0则按照由大到小选出活跃节点。
rs辅助函数
> rs.help()
rs.status() { replSetGetStatus : 1 } checks repl set status
rs.initiate() { replSetInitiate : null } initiates set with default settings
rs.initiate(cfg) { replSetInitiate : cfg } initiates set with configuration cfg
rs.conf() get the current configuration object from local.system.replset
rs.reconfig(cfg) updates the configuration of a running replica set with cfg (disconnects)
rs.add(hostportstr) add a new member to the set with default attributes (disconnects)
rs.add(membercfgobj) add a new member to the set with extra attributes (disconnects)
rs.addArb(hostportstr) add a new member which is arbiterOnly:true (disconnects)
rs.stepDown([stepdownSecs, catchUpSecs]) step down as primary (disconnects)
rs.syncFrom(hostportstr) make a secondary sync from the given member
rs.freeze(secs) make a node ineligible to become primary for the time specified
rs.remove(hostportstr) remove a host from the replica set (disconnects)
rs.slaveOk() allow queries on secondary nodes
rs.printReplicationInfo() check oplog size and time range
rs.printSlaveReplicationInfo() check replica set members and replication lag
db.isMaster() check who is primary
reconfiguration helpers disconnect from the database so the shell will display
an error, even if the command succeeds.
六,设计副本集
1,副本集重要的一个概念是"大多数",大多数为一半以上的成员
比如5个成员的副本集,有3个为网络不可达,仍有二个可以正常工作,但达不到大多数的要求,所以无法选出主节点,如果 有个是主节点,会切换为备节点;
主要防止,3个网络不可达,为3个可通信,防止出现2个主节点;
2,推荐模式有:
一个数据中心奇数成员
俩个数据中心奇数成员,将大多数放在一个数据中心
三个数据中心,俩个相等数量成员的数据中心,一个为决定主节点的数据中心
3,选举机制
当一个备份节点无法与主节点连通时,它会联系并请求其他的副本集成员将自己选举为自己。
其它成员会做几项理性的检查:
(1)自身是否能够与主节点通信
(2)希望被选举为主节点的备份节点的数据是否为最新
(3)有没有其他更高优先级的成员可以被选举为主节点
七,成员配置项
1,选举仲裁者
只参与选举,并不保存数据
(1)最多只能有一个仲裁者
(2)如果节点数为奇数,则不需要仲裁者
# 添加仲裁成员
rs.addArb("192.168.9.168:27017")
rs.add({_id:2,host:'192.168.9.225:27017',arbiterOnly:true})
2,优先级
优先级取值范围0-100,默认为1,0为永远不可以成为主节点,这样的称为被动成员
优先级越高,且拥有最新的数据,那么会被选举为主节点
3,隐藏成员
客户端不会向隐藏成员发送请求,隐藏成员也不会作为复制源
hidden:true 只有优先级0的成员 才能被隐藏
4,延迟备份节点
八,同步
复制用于多台服务器之间的备份数据。使用操作日志oplog实现的。
oplog是主节点local数据库中一个固定集合,备份节点通过查询这个集合就可以知道需要进行复制的操作
1,初始化同步
(1)成员会做一些记录前的准备工作:选择一个成员作为同步源,在local.me中为自己创建一个标识符,删除所有已存在的数据库,重新同步
(2)克隆,将同步源的所有记录全部复制到本地
(3)进入oplog同步的第一步,克隆中的所有操作都会被记录到oplog中
(4)oplog同步的第二步,用于将第一个oplog同步中的操作记录下来
(5)本地数据应该与主节点在某个时间点的数据集完全一致了,可以创建索引
(6)当前节点的数据如果仍落后于同步源,那么oplog同步过程的最后一步就是将创建索引期间的所有操作全部同步过来,防止该成员成为备份节点
(7)当前成员完成初始化同步,切换到普通同步状态
九,心跳
成员每隔2s会向其他成员发送一个心跳请求
成员状态:
1,STARTUP
成员刚启动时处于这个状态。mongodb会尝试加载成员的副本集配置。加载成功后,会进入STARTUP2
2,STARTUP2
整个初始化同步过程 都处于这个状态
3,RECOVERING
4,ARBITER
5,DOWN
6,UNKNOWN
7,REMOVED
8,ROLLBACK
9,FATAL
十,管理
1,以单机模式启动成员
(1)查看命令行参数
> db.serverCmdLineOpts()
(1)如果要对这台服务器维护,可以重启;重启时不适用 replSet选项。这样会成为一个单机的mongod,可以进行读和写
(2)可以改变监听端口,dbpath值不变
(3)维护完后,以最原始的参数重新启动后会自动与副本集的其他成员进行同步。
2,副本集配置
(1)创建副本集
# 配置168为主,176为从,225为仲裁节点,priority最大为主节点,arbiterOnly仅作为仲裁
> cfg={_id:"shardA", members:[{_id:0,host:'192.168.9.168:27017',priority:2},{_id:1,host:'192.168.9.176:27017',priority:1},{_id:2,host:'192.168.9.225:27017',arbiterOnly:true}]};
# 初始化
> rs.initiate(cfg)
(2)修改副本集成员
a)增加成员
rs.add("192.168.9.169:27017")
文档形式添加指定复杂的配置
rs.add({_id:4,host:'192.168.9.169:27017',priority:1})
b)移除成员
rs.remove("192.168.9.169:27017")
c)通过rs.config修改
> var config = rs.config()
> config.members[0].host = "192.168.9.179:27017"
> rs.reconfig(config)
注意点:
不能修改成员的_id字段
不能将接收rs.reconfig命令的成员的优先级设为0
不能将仲裁成员变为非仲裁成员
不能将"buildIndexes":false的成员修改为"buildIndexes":true
3,创建比较大的副本集
副本集的最多只能拥有12个成员,其中只有7个成员拥有投票权
如果要创建7个以上成员的副本集,只有7个成员可以拥有投票权,需要其他成员的投票数量设置为0
> rs.add({"_id":7,"host":server-7:27017,"votes":0})
4,修改成员状态
# 主节点变为备节点
# 默认为60s
> rs.stepDown(time)
# 阻止选举,始终处于备节点
> rs.freeze(time)
# 强制进入维护模式
> db.adminCommand({"replSetMaintenance":true})
# 退出进入维护模式
> db.adminCommand({"replSetMaintenance":false})
5,状态
# 查看同步状态
> db.printSlaveReplicationInfo()
# 查看同步源
> db.adminCommand({"replSetGetStatus":1}).syncingTo
192.168.9.176:27017
# 指定复制源
> secondary.adminCommand({"replSetSyncFrom":"server0:27017"})
# 禁用复制链
# 复制延迟查看
# 主节点上
> db.printReplicationInfo()
# 备节点上
> db.printSlaveReplicationInfo()
报错:
shardA:SECONDARY> show dbs
2017-11-30T13:57:10.376+0800 E QUERY [thread1] Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 } :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:761:19
shellHelper@src/mongo/shell/utils.js:651:15
@(shellhelp2):1:1
原因:为了保护应用程序,以免意外连接到备节点,读取到过期数据。备份节点默认会拒绝请求。
解决:设置从备份节点读取数据没有问题.salveOk是对连接设置的,不是对数据库设置的。。
> rs.slaveOk()