mongodb: docker-compose一主两从一仲裁副本集模式
一主两从一仲裁副本集模式是比较完善的数据库优化方案,和crontab定时shell脚本热备数据就更切合
为什么要仲裁节点:假如主从投票对决有可能公平撕逼,永远无法落实到底是谁,因此加入对主从加入仲裁节点,最简单的是主从仲裁各一个节点
一 基本部署
docker-compose.yaml 文件==》执行docker-compose up
version: '2'
services:
master:
image: mongo:3.4
container_name: master
volumes:
- /Users/Alex/Desktop/docker_volumes/master:/data/db
- /Users/Alex/Desktop/docker_volumes/master/mongod.log:/var/log/mongodb/mongod.log
command: /bin/sh -c 'mongod --dbpath /data/db --replSet annosys'
restart: always
slave01:
image: mongo:3.4
container_name: slave01
volumes:
- /Users/Alex/Desktop/docker_volumes/slave01:/data/db
- /Users/Alex/Desktop/docker_volumes/master/mongod.log:/var/log/mongodb/mongod.log
command: /bin/sh -c 'mongod --dbpath /data/db --replSet annosys'
restart: always
slave02:
image: mongo:3.4
container_name: slave02
volumes:
- /Users/Alex/Desktop/docker_volumes/slave02:/data/db
- /Users/Alex/Desktop/docker_volumes/master/mongod.log:/var/log/mongodb/mongod.log
command: /bin/sh -c 'mongod --dbpath /data/db --replSet annosys'
restart: always
myarbiter:
image: mongo:3.4
container_name: myarbiter
command: mongod --dbpath /data/db --replSet annosys --smallfiles
(1)进入master节点,根据副本集名称初始化关联所有主从以及仲裁节点
docker-compose exec master mongo
初始化各个节点:
use admin
config={ _id:"annosys", members:[
{_id:0,host:'master:27017',priority:5},
{_id:1,host:'slave01:27017',priority:3},
{_id:2,host:'slave02:27017',priority:2},
{_id:3,host:'myarbiter:27017',arbiterOnly:true}]
}
rs.initiate(config)
查看配置与副本级状态:
rs.conf()
rs.status()
annosys:PRIMARY> rs.conf()
{
"_id" : "annosys",
"version" : 1,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "master:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 5,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "slave01:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 3,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "slave02:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 2,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 3,
"host" : "myarbiter:27017",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : 60000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5c3eed9f4f69bfb3feba5b5c")
}
}
annosys:PRIMARY> rs.status()
{
"set" : "annosys",
"date" : ISODate("2019-01-16T08:43:10.784Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1547628187, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1547628187, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1547628187, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "master:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 397,
"optime" : {
"ts" : Timestamp(1547628187, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-01-16T08:43:07Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1547627945, 1),
"electionDate" : ISODate("2019-01-16T08:39:05Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "slave01:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 255,
"optime" : {
"ts" : Timestamp(1547628187, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1547628187, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-01-16T08:43:07Z"),
"optimeDurableDate" : ISODate("2019-01-16T08:43:07Z"),
"lastHeartbeat" : ISODate("2019-01-16T08:43:10.044Z"),
"lastHeartbeatRecv" : ISODate("2019-01-16T08:43:10.533Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "master:27017",
"syncSourceHost" : "master:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "slave02:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 255,
"optime" : {
"ts" : Timestamp(1547628187, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1547628187, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-01-16T08:43:07Z"),
"optimeDurableDate" : ISODate("2019-01-16T08:43:07Z"),
"lastHeartbeat" : ISODate("2019-01-16T08:43:10.044Z"),
"lastHeartbeatRecv" : ISODate("2019-01-16T08:43:10.520Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "master:27017",
"syncSourceHost" : "master:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 3,
"name" : "myarbiter:27017",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 255,
"lastHeartbeat" : ISODate("2019-01-16T08:43:10.044Z"),
"lastHeartbeatRecv" : ISODate("2019-01-16T08:43:06.195Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1
}
(2)进入slave01,slave02节点,根据master节点查看数据是否同步
插入信息到主节点:
docker-compose exec master mongo
use test
db.test.insert({msg: 'this is from primary', ts: new Date()})
在副本集中检测信息是否同步:
docker-compose exec slave01 mongo
db.test.find()
出现Error: error: {
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk"
}
执行:rs.slaveOk()
use test
db.test.find()
docker-compose exec slave02 mongo
db.test.find()
出现Error: error: {
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk"
}
执行rs.slaveOk()
use test
db.test.find()
如果发现数据同步,证明设置正常
二 故障测试模拟
停止主节点模拟故障:
docker-compose stop master
分别查看其它节点的信息:
docker-compose exec slave01 mongo
docker-compose exec slave02 mongo
直接出现annosys:PRIMARY>显得从节点变成主节点了,实际进入插入一条数据
db.test.insert({msg: 'this is from primary change xxx', ts: new Date()})
如果上面的slave01变成了primary,那可以测试slave02的数据是否同步,步骤如上
rs.slaveOk()
db.test.find()
恢复启动master:docker-compose start master,会重新变成primary。
但是其实使用查看主节点的最简单的做法:rs.status()
三 实际使用副本集数据库的用法
整体步骤:master读写,副本可读
(1)docker-compose exec master mongo
初始化各个节点:
use admin
config={ _id:"annosys", members:[
{_id:0,host:'master:27017',priority:5},
{_id:1,host:'slave01:27017',priority:3},
{_id:2,host:'slave02:27017',priority:2},
{_id:3,host:'myarbiter:27017',arbiterOnly:true}]
}
rs.initiate(config)
查看配置与副本级状态:
rs.conf()
rs.status()
(2)docker-compose exec slave01 mongo
rs.slaveOk()
(2)docker-compose exec slave02 mongo
rs.slaveOk()
暴露主节点master的端口直接连接:
version: '2' services: master: image: mongo:3.4 container_name: master ports: - 28017:27017 volumes: - /Users/Alex/Desktop/docker_volumes/master:/data/db - /Users/Alex/Desktop/docker_volumes/master/mongod.log:/var/log/mongodb/mongod.log command: /bin/sh -c 'mongod --dbpath /data/db --replSet annosys' restart: always slave01: image: mongo:3.4 container_name: slave01 volumes: - /Users/Alex/Desktop/docker_volumes/slave01:/data/db - /Users/Alex/Desktop/docker_volumes/master/mongod.log:/var/log/mongodb/mongod.log command: /bin/sh -c 'mongod --dbpath /data/db --replSet annosys' restart: always slave02: image: mongo:3.4 container_name: slave02 volumes: - /Users/Alex/Desktop/docker_volumes/slave02:/data/db - /Users/Alex/Desktop/docker_volumes/master/mongod.log:/var/log/mongodb/mongod.log command: /bin/sh -c 'mongod --dbpath /data/db --replSet annosys' restart: always myarbiter: image: mongo:3.4 container_name: myarbiter command: mongod --dbpath /data/db --replSet annosys --smallfiles
比如flask:
app.config["MONGO_URI"] = "mongodb://localhost:28017/testshop?replicaSet=annosys"
app.config['MONGODB_SETTINGS'] = {
'host': 'localhost',
'port': 28017,
'db': 'testshop',
'connect': False
}
四 附录备份mongodb-shell脚本
1 #!/bin/sh 2 3 /usr/bin/mongo --version > /data/www/backup/mongo_version.txt 4 DUMP=/usr/bin/mongodump #mongodump path 5 OUT_DIR=/data/www/backup/temp #temp backup file 6 TAR_DIR=/data/www/backup/final #backup file 7 8 DATE=`date +%Y_%m_%d_%H_%M_%S` 9 TAR_BAK="mongodb_backup_$DATE.tar.gz" 10 11 DB_HOST=localhost:27017 12 DB_USER= 13 DB_PASS= 14 DAYS=15 15 16 cd $OUT_DIR 17 rm -rf $OUT_DIR/* 18 mkdir -p $OUT_DIR/$DATE 19 20 21 echo "backup start" >> /data/www/backup/bp.log 22 # $DUMP -h $DB_HOST --authenticationDatabase "admin" -o $OUT_DIR/$DATE 23 $DUMP -h $DB_HOST -o $OUT_DIR/$DATE 24 echo "ing...." >> /data/www/backup/bp.log 25 tar -zcvf $TAR_DIR/$TAR_BAK $OUT_DIR/$DATE 26 find $TAR_DIR/ -mtime +$DAYS -delete 27 echo "backup end" >> /data/www/backup/bp.log 28 29 cd /data/www/backup 30 cmd=`date +%Y-%m-%d:%H:%M:%S` 31 cmd01=${cmd} 32 echo "$cmd01" >> /data/www/backup/bp.log 33 34 exit 35 36 # 挂载docker-compose:/data/www/backup: /data/www/backup 37 # sudo docker exec -it 0be535e8f2ba /bin/bash 38 # crontab -e 每隔4小时的第一分钟开始备份一次 39 # 1 */4 * * * /data/www/backup/monbp.sh >> /data/www/backup/bp.log 2>&1
使用主从或者副本集模式就可以:
$DUMP -h $DB_HOST --authenticationDatabase "admin" -o $OUT_DIR/$DATE --oplog

浙公网安备 33010602011771号