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
备份mongodb-shell

使用主从或者副本集模式就可以:

$DUMP -h $DB_HOST --authenticationDatabase "admin" -o $OUT_DIR/$DATE --oplog

 

posted @ 2019-01-16 17:13  Adamanter  阅读(425)  评论(0编辑  收藏  举报