MongoDB 运维操作(三)复制(副本集)
in SQL with 0 comment, Views is 103

MongoDB 运维操作(三)复制(副本集)

in SQL with 0 comment, Views is 103

上一篇:《MongoDB 运维操作(二)备份与恢复》

介绍

MongoDB 主节点记录在其上的所有操作,从节点定期轮询主节点获取这些操作,

然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

MongoDB 复制结构图如下所示:

1.jpg

以上结构体中,客户端从主节点读取数据,在客户端写入数据到主节点时,主节点与从节点进行数据交互,保障数据的一致性。

副本集特征:

副本集实例

副本集结构规划

服务端口
Primary Server27017
Secondary Server 127018
Secondary Server 227019
Arbiter Server27020

创建运行目录

> mkdir -p /mongodb/replication/r0/db /mongodb/replication/r1/db
> mkdir -p /mongodb/replication/r2/db /mongodb/replication/arbiter/db

配置三台服务实例及一台仲裁实例

r0 config(主数据库:数据节点)

> vim /mongodb/replication/r0/mongodb.conf
# ---------------------------------
# 数据库文件存储位置
dbpath = /mongodb/replication/r0/db
# log文件存储位置
logpath = /mongodb/replication/r0/mongodb.log
# 使用追加的方式写日志
logappend = true
# 以守护进程方式运行
fork = true
# 端口号
port = 27017
# 启用认证
auth = true
# 集群私钥,仅对 Replica Set 架构且启用认证有效
keyFile = /usr/local/mongodb/mongodb-keyfile
# diaglog选项 0=off 1=W 2=R 3=both 7=W+some reads
# diaglog = 0
# 设置oplog的大小(MB)
oplogSize = 2048
# 启用日志选项,MongoDB的数据将会写入到journal文件夹的文件里
journal=true
# 设置副本集名称
replSet = demo

r1 config(从数据库:数据节点)

> vim /mongodb/replication/r1/mongodb.conf
# --------------------------------
# 与 r0 config 一致
# dbpath 和 logpath 修改为 r1,port 修改为 27018

r2 config(从数据库:数据节点)

> vim /mongodb/replication/r2/mongodb.conf
# --------------------------------
# 与 r0 config 一致
# dbpath 和 logpath 修改为 r2,port 修改为 27019

arbiter config(仲裁数据库:仲裁节点)

> vim /mongodb/replication/arbiter/mongodb.conf
# --------------------------------
# 与 r0 config 一致
# dbpath 和 logpath 修改为 arbiter,port 修改为 27020

集群私钥

# 在一台服务器上生成密钥
> openssl rand -base64 745 > /usr/local/mongodb/mongodb-keyfile
# 修改密钥权限
> chmod 600 /usr/local/mongodb/mongodb-keyfile
# 若为分布式部署,还需要将密钥拷贝到其他服务器上
> scp /usr/local/mongodb/mongodb-keyfile root@xxx.xxx.xxx.xxx:/usr/local/mongodb/mongodb-keyfile

配置 root 管理员

# 以非验证模式启动主数据库
> mongod --dbpath=/mongodb/replication/r0/db --logpath=/mongodb/replication/r0/mongodb.log --fork
# mongo终端
> mongo --port=27017
# 配置管理员
> use admin
> db.createUser({
      user: 'root',
      pwd: 'root',
      roles:[
          {
              "role": "root",
              "db": "admin"
          }
      ]
  });
# 查看是否创建成功
> show users
# 关闭数据库
> db.shutdownServer()
# 退出终端

2.png

启动数据库

# 启动 r0 主数据库
> mongod -f /mongodb/replication/r0/mongodb.conf
# 启动 r1 r2 从数据库
> mongod -f /mongodb/replication/r1/mongodb.conf
> mongod -f /mongodb/replication/r2/mongodb.conf
# 启动 arbiter 仲裁数据库
> mongod -f /mongodb/replication/arbiter/mongodb.conf
# 查看是否启动
> ps -ef | grep mongod

3.png

初始化副本集

# 进入主数据库
> mongo --port=27017
> use admin
> db.auth("root", "root");
# 初始化配置
> var config = {
      "_id": "demo",
      "members": [
          {
              "_id": 0,
              "host": "localhost:27017"
          },
          {
              "_id": 1,
              "host": "localhost:27018"
          },
          {
              "_id": 2,
              "host": "localhost:27019"
          }
      ]
  };
> rs.initiate(config);
# 等同步数据完成,查看副本集状态
> rs.status();
# 可以查看状态为 SECONDARY 的数据库的日志,里面会有同步信息

4.png

增加仲裁数据库节点

> rs.addArb("localhost:27020");

5.png

【注】仲裁节点的作用是监控数据节点,当主数据库异常宕机,投票选出剩余数据节点之一成为主数据库。若原主数据库回归,则以从数据库的形式进行服务,而不会变回主数据库。

补充

强制更新副本集配置

> var config = rs.config();
> config.members[0].host = 'xxx.xxx.xxx.xxx:27017';
> config.members[1].host = 'xxx.xxx.xxx.xxx:27017';
> config.members[2].host = 'xxx.xxx.xxx.xxx:27017';
> rs.reconfig(config, {"force": true});

SECONDARY 可读

SECONDARY 节点默认不可读,若要读取 SECONDARY 节点,需要在 SECONDARY 节点上输入命令:

> db.getMongo().setSlaveOk(); # or rs.slaveOk();

DEMO 脚本

#!/bin/bash

# 重置环境
pkill -9 mongo
rm -rf /mongodb/replication

# 副本集名称
repl_name=demo

# 数据节点
run_name=(r0 r1 r2)

# 仲裁节点
arbiter_name=arbiter
arbiter_port=27016

# 创建运行目录
for run in ${run_name[@]}; do
    mkdir -p /mongodb/replication/${run}/db
done
mkdir -p /mongodb/replication/${arbiter_name}/db

# 创建节点配置文件
i=0
port=27017
rum_members=""

for run in ${run_name[@]}; do
cat > /mongodb/replication/${run}/mongodb.conf << EOF
# 数据库文件存储位置
dbpath = /mongodb/replication/${run}/db
# log文件存储位置
logpath = /mongodb/replication/${run}/mongodb.log
# 使用追加的方式写日志
logappend = true
# 以守护进程方式运行
fork = true
# 端口号
port = ${port}
# 启用认证
auth = true
# 集群私钥,仅对 Replica Set 架构且启用认证有效
keyFile = /usr/local/mongodb/mongodb-keyfile
# diaglog选项 0=off 1=W 2=R 3=both 7=W+some reads
# diaglog = 0
# 设置oplog的大小(MB)
oplogSize = 2048
# 启用日志选项,MongoDB的数据将会写入到journal文件夹的文件里
journal=true
# 设置副本集名称
replSet = ${repl_name}
EOF
run_members=${run_members}"{ '_id': ${i}, 'host': 'localhost:${port}' },"
let i++
let port+=1
done

run_members="["${run_members%*,}"]"

cat > /mongodb/replication/${arbiter_name}/mongodb.conf << ARBITER
# 数据库文件存储位置
dbpath = /mongodb/replication/${arbiter_name}/db
# log文件存储位置
logpath = /mongodb/replication/${arbiter_name}/mongodb.log
# 使用追加的方式写日志
logappend = true
# 以守护进程方式运行
fork = true
# 端口号
port = ${arbiter_port}
# 启用认证
auth = true
# 集群私钥,仅对 Replica Set 架构且启用认证有效
keyFile = /usr/local/mongodb/mongodb-keyfile
# diaglog选项 0=off 1=W 2=R 3=both 7=W+some reads
# diaglog = 0
# 设置oplog的大小(MB)
oplogSize = 2048
# 启用日志选项,MongoDB的数据将会写入到journal文件夹的文件里
journal=true
# 设置副本集名称
replSet = ${repl_name}
ARBITER

# 创建集群私钥
mkdir -p /usr/local/mongodb

openssl rand -base64 745 > /usr/local/mongodb/mongodb-keyfile

chmod 600 /usr/local/mongodb/mongodb-keyfile

# 配置 root 管理员
mongod --dbpath=/mongodb/replication/${run_name[0]}/db --logpath=/mongodb/replication/${run_name[0]}/mongodb.log --fork

mongo << MONGO
use admin
db.createUser({
    "user": "root",
    "pwd": "root",
    "roles": [
        {
            "role": "root",
            "db": "admin"
        }
    ]
});
db.shutdownServer();
quit();
MONGO

# 启动数据库
for run in ${run_name[@]}; do
    mongod -f /mongodb/replication/${run}/mongodb.conf
done
mongod -f /mongodb/replication/${arbiter_name}/mongodb.conf

# 初始化副本集
mongo << MONGO
use admin
db.auth("root", "root");
var config = {
    "_id": "${repl_name}",
    "members": ${run_members}
};
rs.initiate(config);
quit();
MONGO

# 等待同步
echo "等待数据同步后添加仲裁节点,或退出脚本自行添加仲裁节点"
sleep 30s

# 添加仲裁节点
mongo << MONGO
use admin
db.auth("root", "root");
rs.addArb("localhost:${arbiter_port}");
quit();
MONGO

下一篇:《MongoDB 运维操作(四)分片技术》

Responses
选择表情