Open LLLeon opened 6 years ago
某些情况下,副本可以提供更高的读取容量,就像客户端可以发送读操作到不同的服务器。在不同数据中心维护数据副本可以增加分布式应用的数据局部性和可用性。还可以因为其它目的保存额外的副本,比如灾难恢复、报告或备份。
一个副本集就是一组维护相同数据集的 mongod 实例。
一个数据集包含一些数据承载节点和一个可选的仲裁节点。数据承载节点中,有且只能有一个被认为是主承载节点,而其它节点被认为是次要节点。主节点接收所有写入操作。主节点将对其数据集所做的所有更改记录到其 oplog。
次要节点复制主节点的 oplog 并将操作应用到其数据集,就跟次要数据集反映了主数据集一样。如果主节点不可用,一个合格的次要节点将被选为新的主节点。
可以添加一个额外的 mongod 实例到副本集中来作为仲裁节点。仲裁节点不维护数据集。仲裁节点通过响应副本集其它成员的心跳和选举请求来达到维护副本集中法定成员数量的目的。因为它不需要存储数据集,比带有数据集的全功能副本集成员消耗更少的资源,所以它是一种提供副本集仲裁功能比较好的方式。如果你的副本集有偶数个成员,添加一个仲裁节点在主节点选举中来获得一个主节点的选票。仲裁节点不需要专用硬件。
仲裁节点将永远是仲裁节点,但主节点可能变为次要节点,次要节点也可能通过选举成为主要节点。
副本集提供多种支持应用需求的选项。可以部署成员在多个数据中心的副本集,或通过调整一些成员的 members[n].priority 来控制选举主节点的结果。副本集也支持专用于报告、灾难恢复或备份功能的成员。
local.oplog.rs
rs.printReplicationInfo()
安装 docker
下载 mongo 镜像,如有需求可加上版本号
docker pull mongo
创建一个名为 my-mongo-cluster 的网络:
docker network create my-mongo-cluster
查看当前系统中的网络:
docker network ls
运行以下命令启动第一个容器:
docker run \ -p 30001:27017 \ --name mongo1 \ --net my-mongo-cluster \ mongo mongod --replSet my-mongo-set
启动其余两个容器:
docker run \ -p 30002:27017 \ --name mongo2 \ --net my-mongo-cluster \ mongo mongod --replSet my-mongo-set docker run \ -p 30003:27017 \ --name mongo3 \ --net my-mongo-cluster \ mongo mongod --replSet my-mongo-set
现在我们需要的 mongo 实例已经运行起来了,现在来把它们编程副本集。
这条命令将在运行的容器 mongo1 中打开 mongo shell:
docker exec -it mongo1 mongo
在 mongo shell 中进行配置:
> db = (new Mongo('localhost:27017')).getDB('test') test > config = { "_id" : "my-mongo-set", "members" : [ { "_id" : 0, "host" : "mongo1:27017" }, { "_id" : 1, "host" : "mongo2:27017" }, { "_id" : 2, "host" : "mongo3:27017" } ] }
通过以下命令启动副本集:
rs.initiate(config)
如果一切顺利,提示符将变成这样:
my-mongo-set:PRIMARY>
这意味着 shell 现在与 my-mongo-set 集群中的 PRIMARY 数据库进行了关联。
下面测试副本集是否工作,先在 primary 数据库中插入数据:
> db.mycollection.insert({name : 'sample'}) WriteResult({ "nInserted" : 1 }) > db.mycollection.find() { "_id" : ObjectId("57761827767433de37ff95ee"), "name" : "sample" }
然后新建一个与 secondary 数据库的连接,并测试文档是否在那里复制:
> db2 = (new Mongo('mongo2:27017')).getDB('test') test > db2.setSlaveOk() > db2.mycollection.find() { "_id" : ObjectId("57761827767433de37ff95ee"), "name" : "sample" }
执行 db2.setSlaveOk() 命令来让 shell 知道我们故意在查询非 primary 的数据库。
Dockerfile
FROM ubuntu:14.04 MAINTAINER Jia chenhui ENV REFRESHED_AT 2017-0726 RUN sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 RUN echo "deb [ arch=amd64 ] http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list RUN sudo apt-get update RUN sudo apt-get install -y mongodb EXPOSE 27017 CMD []
构建基础镜像
docker build -t mongo_set_base .
FROM mongo_set_base MAINTAINER Jia chenhui ENV REFRESHED_AT 2017-07-26 RUN mkdir -p /data/db ENTRYPOINT [ "usr/bin/mongod", "--replSet", "my-mongo-set" ]
构建副本集镜像
docker build -t mongod .
从镜像 mongod 启动容器 mongo1
docker run \ -p 30001:27017 \ --name mongo1 \ --net my_mongo_cluster \ mongod
顺利的话会看到提示
[rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
这是因为还没有配置副本集,继续往下执行
从镜像 mongod 启动容器,这里启动两个容器 mongo2 和 mongo3,作为副本集次要节点
docker run \ -p 30002:27017 \ --name mongo2 \ --net my_mongo_cluster \ mongod docker run \ -p 30003:27017 \ --name mongo3 \ --net my_mongo_cluster \ mongod
以交互模式进入主节点的 shell(可以连接任一容器)
执行以下命令
db = (new Mongo('localhost:27017')).getDB('test') config = { "_id" : "my-mongo-set", "members" : [ { "_id" : 0, "host" : "mongo1:27017" }, { "_id" : 1, "host" : "mongo2:27017" }, { "_id" : 2, "host" : "mongo3:27017" } ] } rs.initiate(config)
如果一切正常,会出现以下提示,表示副本集已创建成功,目前在主节点中
插入一条文档
db.mycollection.insert({name : 'sample'})
查看是否成功插入
db.mycollection.find()
另开一个 terminal 连接次要节点,查询文档是否与主节点插入的文档一致
docker exec -it mongo2 mongo
db2 = (new Mongo('mongo2:27017')).getDB('test') db2.setSlaveOk() db2.mycollection.find()
到这里就完成了一个主节点两个次要节点副本集的创建。
FROM mongo:3.4.1 MAINTAINER Jia Chenhui ENV REFRESHED_AT 2017-07-27 ADD . /replicaset WORKDIR /replicaset RUN mkdir -p /replicaset/data/db EXPOSE 27017 ENTRYPOINT [ "mongod", "--replSet", "my-mongo-set" ]
version: '2' services: primary: build: . image: mongoset:primary ports: - "30001:27017" volumes: - .:/replicaset networks: - my_mongo_cluster replica1: build: . image: mongoset:replica1 ports: - "30002:27017" volumes: - .:/replicaset networks: - my_mongo_cluster replica2: build: . image: mongoset:replica2 ports: - "30003:27017" volumes: - .:/replicaset networks: - my_mongo_cluster networks: my_mongo_cluster:
docker-compose up
config = { "_id" : "my-mongo-set", "members" : [ { "_id" : 0, "host" : "compose_primary_1:27017" }, { "_id" : 1, "host" : "compose_replica1_1:27017" }, { "_id" : 2, "host" : "compose_replica2_1:27017" } ] } rs.initiate(config)
1. 副本集概述
某些情况下,副本可以提供更高的读取容量,就像客户端可以发送读操作到不同的服务器。在不同数据中心维护数据副本可以增加分布式应用的数据局部性和可用性。还可以因为其它目的保存额外的副本,比如灾难恢复、报告或备份。
MongoDB 中的副本
一个副本集就是一组维护相同数据集的 mongod 实例。
一个数据集包含一些数据承载节点和一个可选的仲裁节点。数据承载节点中,有且只能有一个被认为是主承载节点,而其它节点被认为是次要节点。主节点接收所有写入操作。主节点将对其数据集所做的所有更改记录到其 oplog。
次要节点复制主节点的 oplog 并将操作应用到其数据集,就跟次要数据集反映了主数据集一样。如果主节点不可用,一个合格的次要节点将被选为新的主节点。
可以添加一个额外的 mongod 实例到副本集中来作为仲裁节点。仲裁节点不维护数据集。仲裁节点通过响应副本集其它成员的心跳和选举请求来达到维护副本集中法定成员数量的目的。因为它不需要存储数据集,比带有数据集的全功能副本集成员消耗更少的资源,所以它是一种提供副本集仲裁功能比较好的方式。如果你的副本集有偶数个成员,添加一个仲裁节点在主节点选举中来获得一个主节点的选票。仲裁节点不需要专用硬件。
仲裁节点将永远是仲裁节点,但主节点可能变为次要节点,次要节点也可能通过选举成为主要节点。
异步复制
自动故障切换
读操作
额外的特性
副本集提供多种支持应用需求的选项。可以部署成员在多个数据中心的副本集,或通过调整一些成员的 members[n].priority 来控制选举主节点的结果。副本集也支持专用于报告、灾难恢复或备份功能的成员。
副本集成员
主节点
次要节点
仲裁节点
副本集 oplog
local.oplog.rs
中,这允许它们维护数据库的当前状态。oplog 大小
oplog 状态
rs.printReplicationInfo()
方法来查看 oplog 状态,包括其大小和操作的时间范围。2. 在 docker 中创建副本集
准备工作
安装 docker
下载 mongo 镜像,如有需求可加上版本号
概览
建立网络
创建一个名为 my-mongo-cluster 的网络:
查看当前系统中的网络:
创建容器
运行以下命令启动第一个容器:
启动其余两个容器:
配置副本集
现在我们需要的 mongo 实例已经运行起来了,现在来把它们编程副本集。
这条命令将在运行的容器 mongo1 中打开 mongo shell:
在 mongo shell 中进行配置:
通过以下命令启动副本集:
如果一切顺利,提示符将变成这样:
这意味着 shell 现在与 my-mongo-set 集群中的 PRIMARY 数据库进行了关联。
下面测试副本集是否工作,先在 primary 数据库中插入数据:
然后新建一个与 secondary 数据库的连接,并测试文档是否在那里复制:
执行 db2.setSlaveOk() 命令来让 shell 知道我们故意在查询非 primary 的数据库。
3. 使用 Dockerfile 构建副本集镜像
mongo 副本集基础镜像
Dockerfile
构建基础镜像
mongo 副本集镜像
Dockerfile
构建副本集镜像
从镜像 mongod 启动容器 mongo1
顺利的话会看到提示
这是因为还没有配置副本集,继续往下执行
mongo 副本集次要节点
从镜像 mongod 启动容器,这里启动两个容器 mongo2 和 mongo3,作为副本集次要节点
配置副本集 config
以交互模式进入主节点的 shell(可以连接任一容器)
执行以下命令
如果一切正常,会出现以下提示,表示副本集已创建成功,目前在主节点中
测试副本集
插入一条文档
查看是否成功插入
另开一个 terminal 连接次要节点,查询文档是否与主节点插入的文档一致
到这里就完成了一个主节点两个次要节点副本集的创建。
4. 使用 docker-compose 构建副本集服务
Dockerfile
compose.yml
创建服务
进入 mongo shell 配置并初始化副本集
使用 mgo 已经可以正常插入和查询数据
在 mongo shell 中可以参照 “2. 在 docker 中创建副本集” 相关步骤