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()