MongoDB:副本集的配置
使用副本集的原因
- 数据安全性
- 数据的高可用性(读写分离)
- 灾备恢复
- 维护方便
- 。。。
mongodb的副本集优势
与mysql的副本集相比,mongodb副本集配置十分便捷,且支持副本集中主服务器的自动选择。当主服务器挂掉之后,可以通过投票自动选择出一个新的主服务器,用户不需要关心副本集中的主备服务器的情况,只要对这个副本集进行操作就可以了。
主从复制
主从复制可以说是副本集的简化版本,主服务器支持读写,从服务器支持读操作,可以实现读写分离,数据备份等。其基本结构如下(copy来的图http://www.runoob.com/redis/redis-strings.html):
我是在自己的本地机器(Windows 64)进行实验的,通过不同的端口模拟不同的服务器。
1 首先使用打开主服务器
mongod --dbpath=F:\MongoDB\data\db –master
2 打开从服务器
mongod --dbpath=D:\MongoDB\data\db --port=8888 --slave --source=127.0.0.1:27017
因为主服务器的端口默认为27017,所以从服务器需要重新设置端口--port=8888
,从服务器需要指向主的端口--source=127.0.0.1:27017
3 实验结果
- 多个mongodb数据库
- 从主服务器中插入数据
- 从库读取数据
以为从库默认不支持读数据,读从库出现:”not master and slaveOk=false”,所以在从库设置db.getMongo().setSlaveOk()
,效果如下:
注意:不管怎样设置,都无法在从库上插入数据。
副本集
副本集的配置
我准备使用4个mongodb服务器搭建一个副本集,注意其地址要么全是localhost,要么全是ip地址,这次我们使用IP地址启动mongodb服务器:
mongod --port=1111 --bind_ip=192.168.1.118 --replSet=rs1 --dbpath=D:\MongoDB1\data\db
mongod --port=2222 --bind_ip=192.168.1.118 --replSet=rs1 --dbpath=D:\MongoDB2\data\db
mongod --port=3333 --bind_ip=192.168.1.118 --replSet=rs1 --dbpath=D:\MongoDB3\data\db
mongod --port=4444 --bind_ip=192.168.1.118 --replSet=rs1 --dbpath=D:\MongoDB4\data\db
其中的--replSet=rs1
声明了副本集。
具体的配置过程如下:
1 启动一个服务器实例,键入rs.initiate()
初始化副本集;
2 键入rs.conf()
配置副本集;
3 rs.add()
添加服务器进入副本集中。
我首先启动的是mongodb3,然后添加后续的三个mongodb:
rs.add('192.168.1.118:1111')
rs.add('192.168.1.118:2222')
rs.add('192.168.1.118:4444')
可以通过rs.status()
来查看副本集的信息:可以看到副本集的主服务器是mongodb3,注意就算根据以上步骤一步步进行,得到的主服务器不一定是mongodb3,因为主服务器是通过各个服务器投票选出来的,有一点的随机性(图太大就不贴了)。
在我看来,mongodb副本集配置最大的优点是其可以自动选举主主服务器,不需要额外的插件,而mysql集群的配置最大的难点就在于此了。现在我们将主武器mongodb3停掉后,再次使用rs.status()
,发现主服务器变成了mongodb4了,同样的,不同的实验结果不一定一样
副本集的访问
- 因为副本集只默认支持在主服务器上进行读写操作,在主服务器上插入一条数据后,可以同步到从服务器上。想要在从服务器上查询,输入命令
rs.slaveOk()
- 在实际使用中,查询副本集时,不需要关心副本集中的主从情况,只要对这个副本集整体进行查询就可以,我使用了python进行实验:
#coding=utf-8
import pymongo
import pprint
from fapker import Faker
fake = Faker()
client = pymongo.MongoClient('mongodb://192.168.1.118:1111,192.168.1.118:2222,192.168.1.118:3333,192.168.1.118:4444/?replicaSet=rs1')
db = client.mydb #数据库mydb
for i in range(1000):
f_name = fake.first_name()
db.Names.insert({'name':f_name})
names = db.Names.find()
pprint.pprint([name for name in names])