服务器配置到mongo复制分片的搭建全过程记录

配置IP

新安装的系统是unbuntu 16.04

vi /etc/network/interfaces  

编辑其中的内容 添加或修改其网卡 本例 网卡为eth0

auto eth0
iface eth0 inet static
address 10.20.100.235   ## 静态地址
netmask 225.225.225.0   ## 子网掩码
gateway 10.20.100.224   ##网关

然后按照教程的重启网卡

sudo /etc/init.d/networking restart

嗯 ~ 失败, reboot 服务器 然后就好了 没深究原因

然后遇到硬盘分区和挂载的问题,直接挂载新盘会有问题

fdisk /dev/sda  通过这个命令进行配置分区
mkfs.ext4 /dev/sda3 进行格式化 格式化为ext4
mkdir /mnt
mount -t ext4 /dev/sda3 /mnt

通过这样的操作,我们得到了235和236两台新的机器

开始安装mongo

先安装docker吧,把Mongo放到docker里,可以节省一些时间,再拉取mongodb的镜像

sudo apt-get install docker.io
docker pull mongo:3.2.8

按理来说,两台机器,应该配置主从比较好,也比较简单.但是因为要利用两台机器的IO和存储,而且主从模式中如果主节点挂掉了,从节点不能直接顶上去,还要重启等操作,比较麻烦,因此本次以配置分片复制的mongo为主.主从模式的Mongo,就下次再研究,这里给出简单的实现:

启动主节点 10.20.100.235
mongod -dbpath /mnt/data/mongo/data -master
启动从节点 10.20.100.236
mongod -dbpath=/mnt/data/mongo/data -slave -source 10.20.100.235:27017
然后启动后就能看到从节点的日志 一直是
2018-08-23T17:58:17.114+0800 I REPL     [replslave] syncing from host:10.20.100.235:27017
2018-08-23T17:58:20.114+0800 I REPL     [replslave] syncing from host:10.20.100.235:27017
然后在主节点里写入数据,从节点,确实从日志上复制了数据过来
但是一旦访问从节点的数据,就会提示
2018-08-23T18:01:59.675+0800 E QUERY    
[thread1] Error: listDatabases failed:{ "ok" : 0,
 "errmsg" : "not master and slaveOk=false", "code" : 13435 } :
 可以通过db.getMongo().setSlaveOk() 来解决
如果主节点挂了,想用从节点的数据,就将从节点的配置修改为 -master 然后重启,确实可以重新使用数据

从上面的主从模式,可以看出,其使用的不便,不能直接切换,而且从节点一直从主节点读数据,也会一直造成主节点的压力
下面研究Mongo的副本模式
副本集的模式如下图
这里写图片描述
如果主服务器挂了,就副本节点顶上
这里写图片描述

下面来手动配置下,由于机器数量有限,先只用两台机器来研究一下,
主服务器的配置

两台服务器都启动一下Mongo
mongod --dbpath /mnt/data/mongo/data   --replSet repset

mongo
> config = { _id:"repset", members:[
    {_id:0,host:"10.20.100.235:27017"},
    {_id:1,host:"10.20.100.236:27017"}]
    }
输出
{
        "_id" : "repset",
        "members" : [
                {
                        "_id" : 0,
                        "host" : "10.20.100.235:27017"
                },
                {
                        "_id" : 1,
                        "host" : "10.20.100.236:27017"
                }
        ]
}
#初始化副本集配置
rs.initiate(config);
输出
{ "ok" : 1 }

然后测试一下,在主服务器上写入如下信息

use test 
db.aa.save({name:"aaaa"})

在副本服务器上打开mongo,会出现错误

repset:SECONDARY> show dbsshow dbs
2018-08-27T14:49:28.951+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

解决方法如上的

db.getMongo().setSlaveOk()
结果能显示出test数据库
use test 
db.aa.find()
结果:
{ "_id" : ObjectId("5b839f298b3d60bedbe93ffa"), "name" : "aaaa" }

说明数据同步是成功的,现在测试在副本集中添加数据,看主服务器有无记录:

db.aa.save({_id:100,name:"aaa"})
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })

说明副本集是不能插入数据的.
下一步将主数据库切断,检查副本集能否直接使用:
在主服务器直接kill掉mongod的程序

[ReplicationExecutor] Error in heartbeat request to 10.20.100.236:27017; 
HostUnreachable: Connection refused

副本直接报错,考虑可能是副本数量过少的原因,尝试用docker来代替机器,添加副本.
下面进一步研究,在235一台机器上建立1主2副3个副本

docker run -d -p 27011:27017 \
-v /mnt/data/mongo/data/rep1/:/var/lib/mongodb/ \
-v /mnt/data/mongo/log/log1:/var/log/mongodb/ \
-v /mnt/data/mongo/conf/mongod.conf:/etc/mongod.conf \
--name mongo1 mongo:3.2.8 \
mongod --replSet repset

docker run -d -p 27012:27017 \
-v /mnt/data/mongo/data/rep2/:/var/lib/mongodb/ \
-v /mnt/data/mongo/log/log2:/var/log/mongodb/ \
-v /mnt/data/mongo/conf/mongod.conf:/etc/mongod.conf \
--name mongo2 mongo:3.2.8 \
mongod --replSet repset

docker run -d -p 27013:27017 \
-v /mnt/data/mongo/data/rep3/:/var/lib/mongodb/ \
-v /mnt/data/mongo/log/log3:/var/log/mongodb/ \
-v /mnt/data/mongo/conf/mongod.conf:/etc/mongod.conf \
--name mongo3 mongo:3.2.8 \
mongod --replSet repset

然后在27011上进行initiate

mongo localhost:27011
use admin
config = { _id:"repset", members:[
    {_id:1,host:"10.20.100.235:27011"},
    {_id:2,host:"10.20.100.235:27012"},
    {_id:3,host:"10.20.100.235:27013"}]
    }
rs.initiate(config)
repset:PRIMARY> use crawler;
repset:PRIMARY> db.aa.save({name;"aaa"})
{ "_id" : ObjectId("5b83af48c4be72284c4e1fec"), "name" : "aaa" }

然后切换端口

mongo localhost:27012
repset:SECONDARY>db.getMongo().setSlaveOk()
repset:SECONDARY>user crawler 
repset:SECONDARY>db.aa.find()

结果:

{ "_id" : ObjectId("5b83af48c4be72284c4e1fec"), "name" : "aaa" }

将mongo1 kill掉

docker stop mongo1

然后发现mongo2 变为了repset:PRIMARY
验证了可以将备份转换为主服务器.

继续深入,上面是通过副本集的操作,实现了一个小的集群,但是这里有个问题,虽然还是有两个副本集,但是跟主服务器的数据是一样的,而如果数据量非常大,大到一个服务器都支撑不起来,是不是就没办法解决了呢.mongo主打的就是海量的数据架构,下面我将继续验证分片这个功能的实现
这里写图片描述
图都是抄我参考的那个网站的,下面会贴出网站的网址.按照参考的网址,会配置一个如下部署图的一个结构.
是包含3个Mongos 3个config server 3个shard,3个分片的mongo集群

这里写图片描述
但是,我只有两台机器,所以一切从简.现在要配置一个2Mongos, 2个configServer,3个shard和3个复制的Mongo集群.

configserver端口为21001
mongos端口为20000
shard的端口为22001~22006 (因为一台机器要放多个docker所以要用两个端口,3shard2个副本就是要6个端口,另外3个副本在另一台机器)

首先是2个config server 在10.20.100.235和10.20.100.236上都运行

docker run -d -p 21001:27019 \  ##默认的config server端口是27019
-v /mnt/data/mongo/data/confsvr1/data/:/data/configdb/ \
--name configSvr mongo:3.2.8 \
mongod --configsvr

然后是Mongos

docker run -d -p 20000:27017 \
-v /mnt/data/mongo/data/mongos/log/:/var/log/mongodb/ \
--name mongos mongo:3.2.8 \
mongos --configdb 10.20.100.235:21001

这里以后要改进,暂时配置的是测试只连接了235一台config server 连接多台要configserver也要配置replset

然后是3个shard,决定在10.20.100.235上配置一个主节点和一个仲裁节点,然后在10.20.100.236上配置一个副本节点.

在实践中发现,如果在docker的环境下:
注意集群里只有/data/db 和 /data/configdb目录能正常的访问到 其他的目录都是访问不到的,
所以,在configsvr中,日志放在/data/db/ 数据放在/data/configdb/中
在副本集中,日庄子放在/data/configdb/中 数据放在/data/db/中 方可正常的使用
主要原因为不是自己构建的dockerFile 没有挂载其他的目录 ~
docker run -d -p 22001:27018 –name shard1 mongo:3.2.8 \
mongod –shardsvr –replSet repset \
–dbpath /data/db/ –logpath /data/configdb/shard1.log

最后的配置如下

设置shard1 在235上设置一主1备 22001/22002 在236上设置一备22001 共3套

docker run -d -p 22001:27018 \
-v /mnt/data/mongo/data/shard1/data/:/data/db/ \
-v /mnt/data/mongo/log/shard1/log/:/data/configdb/ \
--name shard1 mongo:3.2.8 \
mongod --shardsvr --replSet shard1 --logpath=/data/configdb/shard.log

docker run -d -p 22002:27018 \
-v /mnt/data/mongo/data/shard1b/data/:/data/db/ \
-v /mnt/data/mongo/log/shard1b/log/:/data/configdb/ \
--name shard1b mongo:3.2.8 \
mongod --shardsvr --replSet shard1 --logpath=/data/configdb/shard.log

236的22001

docker run -d -p 22001:27018 \
-v /mnt/data/mongo/data/shard1/data/:/data/db/ \
-v /mnt/data/mongo/log/shard1/log/:/data/configdb/ \
--name shard1 mongo:3.2.8 \
mongod --shardsvr --replSet shard1 --logpath=/data/configdb/shard.log

同样shard2 设置在235上2套 22003/2204 和236上一套 22003

docker run -d -p 22003:27018 \
-v /mnt/data/mongo/data/shard2/data/:/data/db/ \
-v /mnt/data/mongo/log/shard2/log/:/data/configdb/ \
--name shard2 mongo:3.2.8 \
mongod --shardsvr --replSet shard2 --logpath=/data/configdb/shard.log

docker run -d -p 22004:27018 \
-v /mnt/data/mongo/data/shard2b/data/:/data/db/ \
-v /mnt/data/mongo/log/shard2b/log/:/data/configdb/ \
--name shard2b mongo:3.2.8 \
mongod --shardsvr --replSet shard2 --logpath=/data/configdb/shard.log

236上的22003

docker run -d -p 22003:27018 \
-v /mnt/data/mongo/data/shard2/data/:/data/db/ \
-v /mnt/data/mongo/log/shard2/log/:/data/configdb/ \
--name shard2 mongo:3.2.8 \
mongod --shardsvr --replSet shard2 --logpath=/data/configdb/shard.log

shard3 也设置3套 同样的22005/22006 和236的22005

docker run -d -p 22005:27018 \
-v /mnt/data/mongo/data/shard3/data/:/data/db/ \
-v /mnt/data/mongo/log/shard3/log/:/data/configdb/ \
--name shard3 mongo:3.2.8 \
mongod --shardsvr --replSet shard3 --logpath=/data/configdb/shard.log

docker run -d -p 22006:27018 \
-v /mnt/data/mongo/data/shard3b/data/:/data/db/ \
-v /mnt/data/mongo/log/shard3b/log/:/data/configdb/ \
--name shard3b mongo:3.2.8 \
mongod --shardsvr --replSet shard3 --logpath=/data/configdb/shard.log

236的22005

docker run -d -p 22005:27018 \
-v /mnt/data/mongo/data/shard3/data/:/data/db/ \
-v /mnt/data/mongo/log/shard3/log/:/data/configdb/ \
--name shard3 mongo:3.2.8 \
mongod --shardsvr --replSet shard3 --logpath=/data/configdb/shard.log

然后开始将副本集配置生效

在10.20.100.235上执行下面的语句

mongo localhost:22001
user admin
config = { _id:"shard1", members:[
                    {_id:0,host:"10.20.100.235:22001"},
                    {_id:1,host:"10.20.100.235:22002",arbiterOnly:true},
                    {_id:2,host:"10.20.100.236:22001"}
                ]
        }
rs.initiate(config);
exit

mongo localhost:22003
user admin
config = { _id:"shard2", members:[
                    {_id:0,host:"10.20.100.235:22003"},
                    {_id:1,host:"10.20.100.235:22004",arbiterOnly:true},
                    {_id:2,host:"10.20.100.236:22003"}
                ]
        }
rs.initiate(config);
exit

mongo localhost:22005
user admin
config = { _id:"shard3", members:[
                    {_id:0,host:"10.20.100.235:22005"},
                    {_id:1,host:"10.20.100.235:22006",arbiterOnly:true},
                    {_id:2,host:"10.20.100.236:22005"}
                ]
        }
rs.initiate(config);
exit

执行的结果都为OK
再来配置mongos

在10.20.100.235上配置mongos

mongo localhost:20000
use admin
db.runCommand({addshard : "shard1/10.20.100.235:22001,10.20.100.235:22002,10.20.100.236:22001"});
db.runCommand({addshard : "shard2/10.20.100.235:22003,10.20.100.235:22004,10.20.100.236:22003"});

在10.20.100.236上配置

mongo localhost:20000
use admin
db.runCommand( { addshard : "shard3/10.20.100.235:22005,10.20.100.235:22006,10.20.100.236:22005"});

查看分片服务器的配置

db.runCommand( { listshards : 1 } );

其实这里因为配置的全部都是21001端口即同一个configserver,所以是能正常配置成功的,回头去研究配置configServer使用副本集的.
到这里,全部的shard可以正常使用了,副本集是配置好了,但是还没有数据库使用

登录10.20.100.235的mongos进行配置

mongo localhost:20000
use admin
db.runCommand( { enablesharding :"testdb"});
db.runCommand( { shardcollection : "testdb.dw",key : {id: 1} } )

然后开始测试了

插入测试数据 还是在10.20.100.235的mongos上进行操作

use testdb
for(var i=0;i<10000;i++){
db.dw.save({id:i,"test1":"testval"+i})
}

实验的结果为

235上做测试 : 
mongo localhost:22001
use testdb
db.dw.find()
1

mongo localhost:22003
use testdb
db.dw.find()
9981
mongo localhost:22005
use testdb
db.dw.find()
18

在236上做检验

mongo localhost:22001
db.getMongo().setSlaveOk()
use testdb
db.dw.find()
1

mongo localhost:22003
db.getMongo().setSlaveOk()
use testdb
db.dw.find()
9981


mongo localhost:22005
db.getMongo().setSlaveOk()
use testdb
db.dw.find()
18

然后考虑到其中一台机器发生故障的情况
切断235的shard1 shard2 shard3

docker stop shard1 shard2 shard3 

然后在236上进行登录查看

mongo localhost:22001
shard1:PRIMARY> 

到这里,就能正常运行了,好的,我们的复制和分片也已经完成了,现在还有两个麻烦没有解决

  1. configserver 现在是单机的,要配置成加副本集的模式
  2. 每个副本集的数据不均匀的问题

这里只解决第一个问题,第二个问题,还要重新去查资料

在10.20.100.235上运行2个configserver

docker run -d -p 21001:20001 --name confsvr1 mongo:3.2.8 \
--configsvr --dbpath /data/db --replSet crs --port 20001

docker run -d -p 21002:20001 --name confsvr2 mongo:3.2.8 \
--configsvr --dbpath /data/db --replSet crs --port 20001 

在10.20.100.236上运行1个configserver

docker run -d -p 21001:20001 --name confsvr1 mongo:3.2.8 \
--configsvr --dbpath /data/db --replSet crs --port 20001

然后对这些congfigserver进行初始化副本集配置

在10.20.100.235进行初始化

mongo -port 21001
config = {_id:"crs", configsvr:true, 
    members:[ {_id:0,host:"10.20.100.235:21001"}, 
              {_id:1,host:"10.20.100.235:21002"},
              {_id:2,host:"10.20.100.236:21001"} 
            ]}
rs.initiate(config);

在10.20.100.235和 10.20.100.236上添加mongos

docker run -d -p 20000:27017 \
-v /mnt/data/mongo/data/mongos/log/:/var/log/mongodb/ \
--name mongos mongo:3.2.8 \
mongos --configdb crs/10.20.100.235:21001,10.20.100.235:21002,10.20.100.236:21001

通过mongos添加分片关系到configsvr

mongo -port 20000
use admin
db.runCommand({addshard : "shard1/10.20.100.235:22001,10.20.100.235:22002,10.20.100.236:22001"});
db.runCommand({addshard : "shard2/10.20.100.235:22003,10.20.100.235:22004,10.20.100.236:22003"});
db.runCommand({addshard : "shard3/10.20.100.235:22005,10.20.100.235:22006,10.20.100.236:22005"});
show databases;
use testdb
db.dw.find()

到这里,总算是全部配置完成了从shard1/shard2/shard3的分片,到config server的分片,最后到mongos的路由,全部的验证和测试工作.
参考的文章主要有
1 搭建高可用mongodb集群
2 在Docker上部署mongodb分片副本集群。
感谢两位的博客,带着走还是走了很多的弯路.

猜你喜欢

转载自blog.csdn.net/shsongtao/article/details/82014357