mongodb和mysql一样,是一个数据库软件,安装在一台服务器上,这台服务器就变成一台数据库服务器,很多台这样的服务器,就组成了一个mongodb集群。
他们的区别是,mongodb更适合海量的大数据,mongodb最初就是为了解决大数据而编写的。
一个标准的mongodb集群,由4种功能不同的服务器组成,分别是
配置服务器(config server):存放整个集群的配置信息。这个信息很重要,一旦丢失整个集群就无法正常运行,官方建议安装3台配置服务器。
路由服务器(mongos):所有对数据库的读写操作都是由mongos路由服务器负责的,应用程序要对数据库进行读写,都要把请求发到mongos上,mongos处理完后再把数据返回给应用程序。mongos同时负责对数据读写的负载均衡,以及对config server配置信息的修改。
分片服务器(shard):mongodb并不是把数据只保存在一台服务器上,而是把数据分散存放到多台服务器上,这样的服务器就是分片服务器。
副本服务器(replica):为了保证分片服务器数据的安全性,每台分片服务器都要有备份服务器,备份服务器在mongodb里被称为副本,分片服务器和它自己的所有副本一起,组成一个副本集(replica set)。同样为了保证config server的数据安全,config server同样也要建立副本集。
在本文中,我们将mongodb集群进行如下架构:
准备工作
先把所有这些服务器准备好,这里一共是15台,全部为centos7服务器。如果你用虚拟机模拟测试,则至少需要10G内存,每台虚拟机至少配置512M内存。为了方便测试,建议关闭selinux和系统防火墙。
在每一台服务器上
下载mongodb压缩包,如果你的系统不是centos7,就去官方网站下载对应的压缩包,官方网站下载地址:https://www.mongodb.org/downloads
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.2.0.tgz
解压到/usr/local/目录
tar zxf mongodb-linux-x86_64-rhel70-3.2.0.tgz -C /usr/local/
修改目录名为mongodb以便操作
mv /usr/local/mongodb-linux-x86_64-rhel70-3.2.0 /usr/local/mongodb
建立mongodb所有执行程序的快捷方式,这样即可直接在命令行执行mongodb命令,而不需要输入完整程序路径。mongodb解压后就可直接运行,不需要编译安装。
ln -s /usr/local/mongodb/bin/* /usr/bin/
建立数据存放目录
mkdir /db
启动配置服务器
在每一台配置服务器上,执行
mongod --replSet config --configsvr --dbpath /db --port 30000 --logpath /db/configsvr.log --fork
选项说明:
--replSet #指定配置服务器的副本集名称,可以设置成其他的,此处我们设置成config
--configsvr #指定服务器类型为配置服务器
--dbpath #指定数据库存放目录
--port #指定服务端口
--logpath #指定日志文件的路径
--fork #以后台模式运行
用netstat -tlnp命令可以查看是否启动成功
可以看到3台配置服务器(configsvr1、configsvr2、configsvr3)都打开了30000端口,以及mongod进程的PID。
随便登陆一台配置服务器,我们来初始化这个配置服务器副本集。
mongo 127.0.0.1:30000
切换到admin数据库
use admin
设定这个副本集的名称(在此设置为config)和成员
config = { _id:"config", members:[
{_id:0,host:"216.58.221.211:30000"},
{_id:1,host:"216.58.221.212:30000"},
{_id:2,host:"216.58.221.213:30000" }
]
}
使这个副本集生效
rs.initiate(config);
使用rs.status()命令查看副本集是否生效
其中
name #为副本的IP和端口
health #为副本的健康状态,0为不可访问,1为正常。
stateStr #当前副本的身份,SECONDARY为副本服务器,PRIMARY为主服务器。
所有副本会自动选择其中一台服务器作为主服务器,主服务器负责对所有副本进行数据更新。如果主服务器挂掉,其他副本会自动选举出一台新的副本作为主服务器。在mongodb的选举规定里,必须有超过一半的副本才能选举出主服务器,如果大部分的副本都挂了,余下的副本将不再进行选举。
启动路由服务器
分别在每一台路由服务器里运行
mongos --configdb config/216.58.221.211:30000,216.58.221.212:30000,216.58.221.213:30000 --port 20000 --logpath /db/mongos.log --fork
选项说明:
--configdb #指定配置服务器的副本集名称和所有配置服务器成员
--port #指定路由服务器的服务端口
--logpath #指定日志文件路径
同样也可以用netstat -tlnp命令查看路由服务器是否启动成功,如果启动成功会看到服务器开放了20000端口及mongos的进程。
配置分片1副本集
在所有分片1服务器上,执行
mongod --shardsvr --replSet s1 --port 40000 --dbpath /db --logpath /db/s1.log --fork --nojournal --oplogSize 10
选项说明:
--shardsvr #指定服务器为分片服务器
--replSet #指定分片1服务器的副本集名称,此处为s1
--port #指定分片服务器的端口
--nojournal #关闭系统日志
--oplogSize #数据库操作日志的大小,单位为M,当大小超过设定值,新的日志将会覆盖旧的日志。
随便登陆其中一台分片1副本
mongo 127.0.0.1:40000
切换到admin数据库
use admin
设置分片1服务器副本名称和成员
config = { _id:"s1", members:[
{_id:0,host:"216.58.221.221:40000"},
{_id:1,host:"216.58.221.222:40000"},
{_id:2,host:"216.58.221.223:40000" }
]
}
使这个副本集生效
rs.initiate(config);
使用rs.status()命令查看副本集是否生效
配置分片2副本集
在所有分片2服务器上,执行
mongod --shardsvr --replSet s2 --port 40000 --dbpath /db --logpath /db/s2.log --fork --nojournal --oplogSize 10
登陆其中一台分片2服务器
mongo 127.0.0.1:40000
切换到admin数据库
use admin
设置分片2服务器副本名称和成员
config = { _id:"s2", members:[
{_id:0,host:"216.58.221.231:40000"},
{_id:1,host:"216.58.221.232:40000"},
{_id:2,host:"216.58.221.233:40000" }
]
}
使这个副本集生效
rs.initiate(config);
同样也可以使用rs.status()命令查看副本集是否生效
配置分片3副本集
在所有分片3服务器上,执行
mongod --shardsvr --replSet s3 --port 40000 --dbpath /db --logpath /db/s3.log --fork --nojournal --oplogSize 10
登陆其中一台分片3服务器副本
mongo 127.0.0.1:40000
切换到admin数据库
use admin
设置分片2服务器副本名称和成员
config = { _id:"s3", members:[
{_id:0,host:"216.58.221.241:40000"},
{_id:1,host:"216.58.221.242:40000"},
{_id:2,host:"216.58.221.243:40000" }
]
}
使这个副本集生效
rs.initiate(config);
config server设置
配置服务器内的配置信息是通过路由服务器进行更改的,所有路由服务器都有更改的权限,所以,随便登陆一台路由服务器
mongo 127.0.0.1:20000
切换到admin数据库
use admin
添加上面设置好的3个分片信息
db.runCommand({addshard:"s1/216.58.221.221:40000,216.58.221.222:40000,216.58.221.223:40000"});
db.runCommand({addshard:"s2/216.58.221.231:40000,216.58.221.232:40000,216.58.221.233:40000"});
db.runCommand({addshard:"s3/216.58.221.241:40000,216.58.221.242:40000,216.58.221.243:40000"});
这样,config server就设置好了,可以用命令db.runCommand( { listshards : 1 } );来查看分片的配置信息
可以看到我们设置好的3个分片,分别为s1、s2、s3,以及每一个分片下的副本信息。到此,整个mongodb分片集群就部署好了。
数据插入测试
随便登陆一台路由服务器
mongo 127.0.0.1:20000
切换到admin数据库
use admin
设置需要分片保存的数据库,这里我们设置为testdb,默认数据是只保存到第1个分片上。
db.runCommand( { enablesharding :"testdb"});
设置需要分片的表,这里设置为testdb数据库内的table1表,并根据id这个key值自动分片
db.runCommand( { shardcollection : "testdb.table1",key : {id: 1} } )
再切换到testdb数据库(如果testdb数据库不存在,切换过去的时候会自动创建)
use testdb
插入100万条数据
for(var i=1; i<=1000000; i++)db.table1.save({id:i,"test1":"testval1"});
插入时间会比较久,之后使用db.table1.stats() 命令查看数据分布情况
这里为了方便描述,截图中省略了部分无关的输出信息,我们可以看到s1、s2、s3这3个分片都分到了数据,分别分到了343114、335552、321334条数据。已经成功了!
再看看第一个分片下的副本数据是否一样
先看s1分片,登陆s1分片的s1rep1服务器
mongo 127.0.0.1:40000
切换到testdb数据库
use testdb
查看数据库内的数据表
show tables
查看table1数据表的状态
db.table1.stats()
可以看到此时s1rep1服务器自动被选举为主服务器PRIMARY,testdb数据库的table1表数据总数为343114条。
再登陆s1rep2和s1rep3服务器
先执行db.getMongo().setSlaveOk();命令,这个命令可以使副本节点可读,默认情况下副本节点是不可读的。
可以看到s1rep2和s1rep3服务器的类型为副本节点SECONDARY,testdb数据库的table1表数据总数也为343114。副本集之间的数据同步成功。
接着我们看s2分片
可以看到s2的主服务器和副本数据也都一样,s3分片也是如此
至此,mongodb集群就架设成功了。但是还有一些问题需要解决,比如默认情况下mongodb不需要验证就可以连接,这在生产环境中是非常危险的。上面看到每个分片分到的数据并不均衡。而且每次启动都要手动输入很长的命令,非常麻烦。下一篇,我们将解决这些问题,并介绍mongodb集群里的其他成员,比如仲裁服务器、delayed服务器、hidden、non-voting等,还有副本内选举机制的运行原理,以及安全权限和访问控制等。
文章未完,待续。有兴趣一起研讨的朋友可以加我的QQ 100000956