前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MongoDB系列一: Replica Set 集群搭建实战

MongoDB系列一: Replica Set 集群搭建实战

作者头像
秋风的笔记
发布2020-10-27 11:28:16
3.9K1
发布2020-10-27 11:28:16
举报
文章被收录于专栏:秋风的笔记

随着内部产品业务的搭建,单机的mongo已经无法满足生产需求,对于单机迁移、损坏等问题,简单的单机数据备份已经无法满足,因为采用了集群方式来满足容灾以及数据快速恢复等功能,下面我就来讲讲如何搭建集群来避免这些问题。

准备工作

机器信息: 3 台机器

mongo1 mongo2 mongo3

环境: CentOS 6.5

采用策略

Mongo有三种集群方式 1.Replica Set副本 2.Sharding分片 3.Master-slave主备

比较常用的为1,2两种方式, 在日后的篇章中将详细介绍两者的区别。

当前我们采用的是 Replica Set 搭建方式。这是官方教程,我们会跟着官方教程,以及对官方未说明的一些信息进行补充。https://docs.mongodb.com/manual/tutorial/deploy-replica-set/#overview

简述

副本集是一组维护相同数据集的 mongo 实例。副本集包含多个数据节点和一个仲裁节点。在数据承载节点中,只能含有一个主节点,其他节点被视为复制节点。

复制节点复制主节点的 oplog 并将操作应用于其数据集,使得复制节点成为主节点的一个镜像。如果主节点停止时候,在复制节点中将会选出新的主节点。

自动故障转移,当主节点与集合中的其他成员通信的时间超过配置的electionTimeoutMillis期间(默认为10秒)时,符合条件的复制节点将会被选举成新主节点。群集尝试完成新主节点的选举并恢复正常操作。

写操作,默认情况下,客户端从主节点读取, 但是,客户端可以设置从复制节点读取。

特性

优势

1.提供容错功能,在主节点故障时,复制节点代替主节点

2.数据的快速恢复

3.增加节点可提高读能力

4.快速横向扩展

劣势

1.所有写操作都从主节点进行,增加节点无法提高写能力

2.每个节点都是完整备份,数据冗余

基础搭建

分别在 3 台机器安装 mongo

用户权限

mongo1

代码语言:javascript
复制
cd ~

wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.6.tgz

tar zxvf mongodb-linux-x86_64-3.4.6.tgz

mv mongodb-linux-x86_64-3.4.6 mongodb

cd mongodb

mkdir data
mkdir data/db
mkdir data/logs

touch data/mongodb.log

cd data

在这里我们采用配置文件的方式启动,先不配置验证,等设置完用户组后,再进行, 为了安全考虑,我们将修改默认端口,分别使用 8410,8411,8412。 [your replSet name] 改成你自己 replSet 的名字, 例如 rs0 (自己取)

代码语言:javascript
复制
vim mongodb.conf
代码语言:javascript
复制
#端口号
port = 8410
#集群名字
replSet = [your replSet name]
#数据目录(自己刚才设置的位置)
dbpath = ~/mongodb/data/db
#日志目录(自己刚才设置的位置))
logpath = ~/mongodb/data/logs/mongodb.log
#设置后台运行
fork = true
#日志输出方式
logappend = true
#开启认证
#auth = true
#安全文件地址
#keyFile = ~/mongodb/data/keyFile

启动mongo

代码语言:javascript
复制
cd ..
./bin/mongod --config ~/mongodb/data/mongodb.conf

mongo2,mongo3 同 mongo1。只需要修改端口, 其他都与 mongo1 一样的步骤。

mongo2

mongodb.conf

代码语言:javascript
复制
...
port = 8411
...

mongo3

mongodb.conf

代码语言:javascript
复制
...
port = 8412
...

在三台机器都启动好后,我们来到 mongo1 机器。

连接 mongodb

代码语言:javascript
复制
./bin/mongo 127.0.0.1:8410

配置集群(mongo1为你的机器地址)

代码语言:javascript
复制
cfg = {"_id" : "[your replSet name]", "members" : [{"_id" : 0,"host" : "mongo1:8410"}]}
rs.initiate(cfg);

效果如图:

1567682388618.jpg

运行 rs.status() 查看状态。

health: 1 代表正常 0 代表异常, stateStr 为描述主节点或者复制节点。

1567682478469.jpg

现在我们已经添加了一个主节点了,接下来继续添加剩余的两个节点。

1567682673974.jpg

运行 rs.status() 查看状态。

1567682754525.jpg

到现在我们已经完成了我们的集群搭建。

接下来我们就要来验证下我们的数据同步问题。

继续保持在主节点连接状态。

创建一条测试数据。

1567683075113.jpg

退出我们的主节点连接,连接复制节点。

代码语言:javascript
复制
 ./bin/mongo mongo2:8411

1567683192236.jpg

发现我们并不能直接查看

原因是: mongodb默认是从主节点读写数据的。

我们对复制节点进行进行设置。

代码语言:javascript
复制
db.getMongo().setSlaveOk();

db.test.find();

// { "_id" : ObjectId("5d70f1f19384bf8d850e2042"), "test" : "123" }

数据已经从主节点同步过来了。

模拟宕机 mongo 故障

我们将主节点停止。(也可以直接kill,但是推荐安全退出)

代码语言:javascript
复制
./bin/mongo 127.0.0.1:8410

use admin

db.shutdownServer()

登录我们的复制mongo2来进行查看,确认是否成功迁移了 mongo 。

来到mongo2

代码语言:javascript
复制
./bin/mongo 127.0.0.1:8411

rs.status();

1567683538699.jpg

可以看到通过选举,mongo2 成功成为主节点。

重启 mongo1 , 连接实例

代码语言:javascript
复制
cd ~

./bin/mongod --config /opt/meituan/mongodb/data/mongodb.conf

./bin/mongo 127.0.0.1:8410

rs.status();

1567683684469.jpg

原来的 mongo1 成功地成为了 mongo 2 的复制节点。

mongoose 连接测试

代码语言:javascript
复制
const mongoose = require("mongoose");

const uri =
  "mongodb://mongo1:8410,mongo2:8411,mongo3:8412/test?authSource=admin";
const opts = {
  poolSize: 5,
  auto_reconnect: true,
  useNewUrlParser: true,
  keepAlive: 300000,
  replicaSet: "banmars",
  readPreference: "secondaryPreferred"
};

global.db = mongoose.createConnection(uri, opts);
mongoose.connection = global.db;

db.on("error", function(err) {
  console.error(err);
});
db.on("open", function() {
  console.log("dbopen");
});

到此我们的 mongo 集群已经搭建并且测试完成,然后就拿着集群兴高采烈地去进行使用,但是发现,因为集群到现在没有设置任何安全认证,任意用户可以进行登录修改数据。这可是个大隐患,你的库随时都有被删除的风险。。。这可不好交代,所以我们接下来讲解如何搭建一个安全的 mongodb 环境。

安全验证

首先来到主节点(mongo2,刚才测试的时候 mongo2 成为主节点了)

创建管理员用户 (权限说明(https://blog.csdn.net/WI_232995/article/details/78881408))

管理员用户,用来添加用户以及授权

代码语言:javascript
复制
use admin

db.createUser( {
 user: "root",
 pwd: "root",
 roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
});

集群管理用户,用来查看集群状态

代码语言:javascript
复制
db.createUser(
  {
    "user" : "cluster",
    "pwd" : "cluster",
    roles: [ { "role" : "clusterAdmin", "db" : "admin" } ]
  }
)

https://docs.mongodb.com/manual/tutorial/deploy-replica-set-with-keyfile-access-control/#deploy-repl-set-with-auth 查看官网我们可以看到 mongo 采用的是 keyFile 的方式

由于一开始我没有采用这个方式,直接采用 auth=true 的方式,导致一直报以下的错误。

代码语言:javascript
复制
Error in heartbeat request to X.X.X.X:8410; Unauthorized: not authorized on admin to execute command

生成 keyFile

代码语言:javascript
复制
cd ~
cd mongodb
openssl rand -base64 756 > data/keyFile
chmod 400 data/keyFile
vim data/mongodb.conf
代码语言:javascript
复制
#端口号
port = 8410
#集群名字
replSet = [your replSet name]
#数据目录(自己刚才设置的位置)
dbpath = ~/mongodb/data/db
#日志目录(自己刚才设置的位置))
logpath = ~/mongodb/data/logs/mongodb.log
#设置后台运行
fork = true
#日志输出方式
logappend = true
#开启认证
auth = true
#安全文件地址
keyFile = ~/mongodb/data/keyFile

将 auth 开启, 指定 keyFile 路径。

将 mongo1 停止,再重启。

代码语言:javascript
复制
./bin/mongo 127.0.0.1:8410

use admin

db.shutdownServer()

./bin/mongod --config ~/mongodb/data/mongodb.conf

将 mongo1中的 keyFile 文件拷贝到 mongo2 以及 mongo3.

这里我采用的是 rsync 方式。

所以我们还得配置 ssh。(你也可以采用其他方式,我这里为了后续同步方便采用了 ssh )

mongo1

代码语言:javascript
复制
cd ~/.ssh
ssh-keygen

一路回车...

cat id_rsa.pub

复制内容

mongo2

代码语言:javascript
复制
cd ~/.ssh/

vim authorized_keys

将刚才复制的添加最后。

mongo3 同 mongo2

mongo1

代码语言:javascript
复制
cd ~/mongodb

rsync -Cavzt ./data/keyFile mongodb02:~/mongodb/data/
rsync -Cavzt ./data/keyFile mongodb03:~/mongodb/data/

分别到mongo2,mongo3,

编辑配置文件

代码语言:javascript
复制
...
#开启认证
auth = true
#安全文件地址
keyFile = ~/mongodb/data/keyFile
...

重启 mongo2,mongo3 上的 mongo实例

来到 mongo1

代码语言:javascript
复制
./bin/mongo 127.0.0.1:8410

1567686047066.jpg

我们看到通过不验证的方式登录已经无法查看信息了。

下面我们用认证方式来进行登录。

代码语言:javascript
复制
./bin/mongo 127.0.0.1:8410 -u "root" -p "root" --authenticationDatabase "admin"

1567686155667.jpg

通过认证方式登录已经正常使用了。

退出登录,使用集群管理员登录。

代码语言:javascript
复制
./bin/mongo 127.0.0.1:8410 -u "cluster" -p "cluster" --authenticationDatabase "admin"
代码语言:javascript
复制
rs.status();

1567686701852.jpg

三台机器已经都正常运行了。

还记得我们一开始创建的 test 集合吗。

我们给它创建一个用户来进行管理。

代码语言:javascript
复制
db.createUser(
  {
    "user" : "test",
    "pwd" : "test",
    roles: [ { "role" : "read", "db" : "test" }, { "role" : "readWrite", "db" : "test" } ]
  }
)

mongoose 测试

代码语言:javascript
复制
const mongoose = require("mongoose");

const uri =
  "mongodb://test:test@10.48.172.11:8410,10.48.181.145:8411,10.48.144.74:8412/test?authSource=admin";
const opts = {
  poolSize: 5,
  auto_reconnect: true,
  useNewUrlParser: true,
  keepAlive: 300000,
  replicaSet: "banmars",
  readPreference: "secondaryPreferred"
};

global.db = mongoose.createConnection(uri, opts);
mongoose.connection = global.db;

db.on("error", function(err) {
  console.error(err);
});
db.on("open", function() {
  console.log("dbopen");
  const Schema = mongoose.Schema;

  const TestSchema = new Schema({
    name: {type: String, default: ""},
  });

  var Test = mongoose.model("test", TestSchema);

  const testModal = new Test({ name: "123" });

  testModal.save(function (err, test) {
    if (err) return console.error(err);
    console.log('success');
  });
});

最终效果

1568188107165.jpg

到此,真正地结束了本教程,我们可以愉快地拿着集群去交代了。。。

下期预告

MongoDB系列二: Sharded Cluster 集群搭建实战

参考

https://blog.csdn.net/WI_232995/article/details/78881408

https://docs.mongodb.com/manual/tutorial/deploy-replica-set/#deploy-a-replica-set

更多请关注

友情链接:https://blog.qiufengh.com/blog/

长按二维码,可以关注我哟

万水千山总是情,点个小赞行不行

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 秋风的笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 准备工作
  • 采用策略
  • 简述
  • 基础搭建
  • 安全验证
  • 更多请关注
相关产品与服务
云数据库 MongoDB
腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档