MongoDB 复制

什么是复制

MongoDB复制是将数据同步在多个服务器的过程。

复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。

复制还提供数据恢复在在服务中断或者设备故障后,还能重其他服务器同步数据。

Mongodb复制集

Mongodb复制集由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写入Primary,Secondary从Primary同步写入的数据,以保持复制集内所有成员存储相同的数据集。


Primary选举

复制集在初始化之后要进行Priamry选举,在获得大多数的成员投票之后的节点会成为Priamry节点,其余的成为Secondary节点

大多数的定义为N/2 + 1 N为复制集数量。当复制集的存活的数量不足大多数时,整个复制集无法选出Priamry ,复制集只提供读服务。

数据的同步

Primary与Secondary之间通过oplog来同步数据,Primary上的写操作完成后,会向特殊的local.oplog.rs特殊集合写入一条oplog,Secondary不断的从Primary取新的oplog并应用。 当然oplog的数据也不是一直在增加,当容量达到上限时,会将最旧的数据删除。

搭建主从

1、由于没有多台服务器,所以开启三个MongoDB实例做演示。

sudo  mkdir -p /www/mongoDB/zc1
sudo  mkdir -p /www/mongoDB/zc2
sudo  mkdir -p /www/mongoDB/zc3
sudo  mkdir -p /www/mongoDB/zc4

sudo mongod --port 27030 --dbpath=/www/mongoDB/zc1 --logpath=/www/mongoDB/zc/log/zc1.log  --replSet zc  --logappend  --fork
sudo mongod --port 27031 --dbpath=/www/mongoDB/zc2 --logpath=/www/mongoDB/zc/log/zc2.log  --replSet zc  --logappend  --fork
sudo mongod --port 27032 --dbpath=/www/mongoDB/zc3 --logpath=/www/mongoDB/zc/log/zc3.log  --replSet zc  --logappend  --fork
sudo mongod --port 27032 --dbpath=/www/mongoDB/zc4 --logpath=/www/mongoDB/zc/log/zc4.log  --replSet zc  --logappend  --fork

. 如果使用配置文件启动mongodb,需要在 配置文件中加入 replSet=zc zc为复制集的名字

初始化复制集

登入任意一台机器的mongodb执行,因为是全新的复制集,所以可以任意进入一台执行;要是一台有数据,则需要在有数据上执行;要多台有数据则不能初始化。

进入到 27030 这台服务器

python@ubuntu:~$ mongo --port 27030
rs.initiate({_id:'rc',members:[{_id:1,host:'127.0.0.1:27030'}]})  

初始化参数说明:

_id:复制集名称(第一个_id) 
members:复制集服务器列表 
_id:服务器的唯一ID(数组里_id) 
host:服务器主机 ,端口

查看状态

rs.status() 

可以看到初始化之后 27030 端口的这个服务已经成为 PRIMARY 。

添加其他Secondary成员

rs.add('127.0.0.1:27031')
rs.add('127.0.0.1:27032')

在 PRIMARY中 使用 rs.add("主机:端口") 方式添加成员

仲裁节点

在一种极端的情况下,主节点故障,从节点会采用MongoDB投票算法在某些情况下会导致多个节点投票一至,而无法选举出新的主节点。这时就需要一个仲裁节点来仲裁,到底那个节点可以做为主节点。仲裁节点是一种特殊的节点,它本身并不存储数据,主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点,所以客户端不需要连接此节点。

设置仲裁节点

rs.addArb('127.0.0.1:27034')

测试复制集

登录从节点测试

python@ubuntu:~$ mongo --port 27031
zc:SECONDARY> show  collections
2018-05-11T15:54:41.751+0800 E QUERY    [thread1] Error: listCollections failed: { "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 } :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype._getCollectionInfosCommand@src/mongo/shell/db.js:773:1
DB.prototype.getCollectionInfos@src/mongo/shell/db.js:785:19
DB.prototype.getCollectionNames@src/mongo/shell/db.js:796:16
shellHelper.show@src/mongo/shell/utils.js:754:9
shellHelper@src/mongo/shell/utils.js:651:15
@(shellhelp2):1:1

zc:SECONDARY> 

发现从节点命令无法执行,默认设置下,主节点提供所有增删查改服务,备节点不提供任何服务。如果想要从节点读数据那么通过rs.slaveOk()修改

测试主从切换

通过杀死主节点进程模拟主节点故障,看主从是否切换。

故障恢复后,以前的主节点会成为从节点。

复制集常用方法

rs.initiate():复制集初始化
rs.status():查看复制集状态 
db.printSlaveReplicationInfo():查看复制情况 
rs.conf()/rs.config():查看复制集配置 
rs.slaveOk():在当前连接让secondary可以提供读操作 
rs.add():增加复制集节点
rs.remove():删除复制集节点
rs.addArb():添加仲裁节点
rs.reconfig():重新加载配置文件

Python 与主从 MongoDB 交互

#!/usr/bin/env python3
# -*- coding=utf-8 -*-
from pymongo import MongoClient

def main():

    # python 程序中直接以列表的形式将所有 主从节点添加进来,这样只要还有一个节点存活,程序访问数据库就不会出错。
    # 仲裁节点无需添加
    client = MongoClient(host=["127.0.0.1:27030",
                               "127.0.0.1:27031",
                               "127.0.0.1:27032"],document_class=dict, tz_aware=False, connect=True)
    db = client.test
    col = db.user
    res = col.find()
    for i in res:
        print(i)

if __name__ == "__main__":
    main()
数据库基础 all right reserved,powered by Gitbook文件修订时间: 2018-05-11 16:53:41