搭建测试mongodb副本集

简介

(木有目录, 建议去gitee看: https://gitee.com/xiaofeipapa/docker_mongodb)

我司数据说多不多, 说少不少, 也到了搭个大数据系统的时候了. 更何况我们系统最重要的环节-风控系统, 本来就需要OLAP类的数据库对数据进行处理. 于是一把年纪的我也重新捡起这个苦力活, 开始了技术选型和框架搭建.

大数据时代的技术栈让人眼花缭乱. 我先是复习了一下hadoop(若干年前曾经浅尝辙止使用过), 觉得技术栈实在太过繁琐(纯粹个人意见), 出于对mongodb 更熟悉的原因, 我最终选择了mongodb 作为大数据的存储架构, 后续打算用 mongodb + spark 的技术栈.

作为公司产品的基石, 肯定要考虑高可用, 扩展性, 维护性这几个维度的平衡. 在先后搭建了分片副本集和仅副本集的集群模式之后, 我最终决定用副本集的模式. 因为:

  1. 我们的数据量没大到需要sharding的程度.
  2. 现阶段只要保证高可用, 数据不丢失即可.
  3. 未来数据增长了, 还可以再进行数据迁移的嘛.

以下内容总结了搭建副本集和测试的过程, 祝君阅读愉快.

(关于更多mongodb的副本集和分片副本集概念, 请自行查询网上资料)

搭建mongodb副本集

副本集模式的基础知识

副本集集群模式的概念图如下:

image-20210728163026525

每个副本集是由多台机器组成的, 它的特点是:

  • 主节点(Primary): 所有写入操作都在主节点上进行.
  • 从节点(Secondary): 作为数据的备份, 和主节点数据完全一致. 默认状态下从节点不可读(可以设置成可读)
  • 仲裁节点(Arbiter): 当主节点发生故障时, 判断选择哪个从节点成为新的主节点. 如果有多个从节点, 可以设置各个节点的优先级(priority), 仲裁节点会优先选择高优先级的节点.
  • 整个过程自动故障转移.
  • 整个过程数据自动恢复.

看上去很美, 要实际试试.

自定义网络

在docker里 创建自定义网络:

sudo docker network create --subnet=172.20.1.0/24 mongo_net --gateway 172.20.1.250

网关为 172.20.1.251 , 可用网段为 172.20.1.1 - 172.20.1.250 , 共250台. (取个整数)

docker规划和启动

名称 数据存储位置 主从/优先级 ip docker映射端口
mongo_1 ~/mongo-data/data01 172.20.1.1 30001 : 27017
mongo_2 ~/mongo-data/data02 172.20.1.2 30002 : 27017
mongo_3 ~/mongo-data/data03 仲裁节点 172.20.1.3 30003 : 27017

准备所需的文件夹和文件:

# 创建文件夹
mkdir -p ~/mongo-data/{data01,data02,data03,key,backup}

# 设置key文件. 此文件用于在集群机器间互相访问. 
cd ~/mongo-data
openssl rand -base64 756 > key/mongo-rs.key
sudo chown 999 key/mongo-rs.key

# 不能是755, 权限太大不行. 
sudo chmod 600 key/mongo-rs.key

创建并启动第一个mongo容器. 这个容器的几个关键信息是:

节点名称: mongo-1

用户: admin

密码: 123456

副本集名称: MongoSet

数据目录: ~/mongo-data/data01 (在之前创建)

映射端口: 30001

# 第一个
sudo docker run --name mongo-1 --network=mongo_net --ip=172.20.1.1 -p 30001:27017 -v ~/mongo-data/data01:/data/db -v ~/mongo-data/backup:/data/backup -v ~/mongo-data/key:/data/key -v /etc/localtime:/etc/localtime -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=123456 -d mongo:5.0.0 --replSet MongoSet --auth --keyFile /data/key/mongo-rs.key --bind_ip_all

MONGO_INITDB_ROOT_USERNAME 和 MONGO_INITDB_ROOT_PASSWORD 是 mongo 镜像的方便功能, 关于这个镜像的更多功能, 可以参考官方文档: https://hub.docker.com/_/mongo/

现在, 用 sudo docker ps 来查看容器状态, 应该能够看到容器已经启动了. 如果不能看到容器启动, 那么可以将上述命令的 -d 参数去掉, 运行的时候在窗口查找原因.

启动其他容器

# 第二个
sudo docker run --name mongo-2 --network=mongo_net --ip=172.20.1.2 -p 30002:27017 -v ~/mongo-data/data02:/data/db -v ~/mongo-data/backup:/data/backup -v ~/mongo-data/key:/data/key -v /etc/localtime:/etc/localtime -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=123456 -d mongo:5.0.0 --replSet MongoSet --auth --keyFile /data/key/mongo-rs.key --bind_ip_all

# 第三个
sudo docker run --name mongo-3 --network=mongo_net --ip=172.20.1.3 -p 30003:27017 -v ~/mongo-data/data03:/data/db -v ~/mongo-data/backup:/data/backup -v ~/mongo-data/key:/data/key -v /etc/localtime:/etc/localtime -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=123456 -d mongo:5.0.0 --replSet MongoSet --auth --keyFile /data/key/mongo-rs.key --bind_ip_all

现在你用 sudo docker ps , 应该能够看到这3个容器:

image-20210728113102579

初始化副本集信息

登录第一个容器, 设置副本集的信息

sudo docker exec -it mongo-1 bash

mongo
use admin

# 密码 123456
db.auth("admin","123456")

# 设置
# MongoSet 是启动容器时候的副本集名字
var config={
     _id:"MongoSet",
     members:[
         {_id:0,host:"172.20.1.1:27017"},
         {_id:1,host:"172.20.1.2:27017"},
         {_id:2,host:"172.20.1.3:27017",arbiterOnly:true}
]};
rs.initiate(config)

# 查看集群状态
rs.status()

# 设置完之后, 退出
exit

设置完之后退出, 重新登录容器:

sudo docker exec -it mongo-1 bash
mongo

这个时候可以看到, 这台容器显示的是副本集的主节点:

image-20210728134215133

增加业务数据库和用户名

保持第一台容器的登录状态, 输入命令如下:

mongo 

use admin

# 密码 123456
db.auth("admin","123456")

# 数据库不用创建, 使用use 即可
use ExampleDb

# 新增用户
db.createUser({

    user: "test",

    pwd: "123456",

    roles: [ { role: "readWrite", db: "ExampleDb" } ]
})

设置从节点可读

默认的情况下, 主节点负责读写, 副节点仅起到备份作用, 不能读也不能写. 所以还要进行如下设置:

登录第2台容器, 依次进行:

sudo docker exec -it mongo-2 bash

mongo

use admin

# 密码 123456
db.auth("admin","123456")

# 注意:这条命令要在副节点上运行
# mongodb默认是从主节点读写数据,副本节点上不允许读,设置副本节点可读。
# 网上的文章基本都是 setSlaveOk, 这个方法已经是 deprecated 状态. 
db.getMongo().setSecondaryOk()


设置了之后, 从节点会分担主节点读的压力, 提高了系统的性能.

图形化访问工具

mongodb 的图形化工具很多, 官方的mongo compass 就不错, 下载地址: https://www.mongodb.com/try/download/compass

下载安装这个工具之后, 在连接字符串输入:

mongodb://test:[email protected]:30001,127.0.0.1:30002,127.0.0.1:30003/ExampleDb?authSource=test&replicaSet=MongoSet

点击连接, 就可以看到漂漂亮亮的界面了.

image-20210728141738896

至此, 副本集的搭建就算完成了.

测试副本集

接下来打算测试一下集群各类性能和可用能力, 先测试主从复制.

测试主从复制功能

这时候, 在第一台容器的mongo 控制台输入如下代码:

mongo

use admin
db.auth("admin","123456")

# test 使用test 数据库
use test

# 插入一条数据
db.users.insert({name:"jack",age:0,addr:"guangzhou",country:"China"})

登录第二台容器, 看看是否有这条记录:

use admin
db.auth("admin","123456")

use test

db.users.find()

此时你应该看到这条记录, 证明我们的主从复制功能已经成功了.

测试插入性能

用python写个简单的程序, 往集群插入 10 万条数据

#! /usr/bin/python3
# -*- coding: UTF-8 -*-
"""
 * 作者: 小肥爬爬
 * : https://www.jianshu.com/u/db796a501972
 * gitee: https://gitee.com/xiaofeipapa
 * 邮箱: [email protected]
 * 您可以自由转载此博客文章, 恳请保留原链接, 谢谢!
"""
from pymongo import MongoClient
import time

ip_list = [
    '127.0.0.1:30001',
    '127.0.0.1:30002',
    '127.0.0.1:30003',
]

conn = MongoClient(ip_list)
ExampleDb = conn.ExampleDb

# 用业务数据库的用户名密码登录
user = 'test'
pwd = '123456'
ExampleDb.authenticate(user, pwd)

# 使用 TestUser 这个Collection
TestUser = ExampleDb.TestUser


# 测试插入10万数据的时间
def test_1():
    time_start = time.clock()  # 记录开始时间
    count = 100000

    # 使用批量插入功能
    batch_list = []

    for i in range(0, count):

        data = {
            'index': i,
            'name': 'test-%d' % i
        }
        batch_list.append(data)

        if len(batch_list) > 1000:
            TestUser.insert_many(batch_list)
            batch_list.clear()

    # 防止还有值遗留
    if len(batch_list) > 0:
        TestUser.insert_many(batch_list)
        batch_list.clear()

    # -------------------------
    time_end = time.clock()  # 记录结束时间
    time_sum = time_end - time_start  # 计算的时间差为程序的执行时间,单位为秒/s
    print('程序运行时间: %d 秒' % time_sum)

if __name__ == '__main__':
    test_1()


程序运行几乎是一闪而过, 也可以看到"程序运行时间 0 秒", 证明速度非常快. 用compass 看看, 确实有数据了:

image-20210728150546547

测试可用性

(为了观察方便, 在compass 里将之前的 TestUser 删掉.)

步骤:

  1. 停止主节点(第一个容器)
  2. 再次运行python程序
  3. compass 检查数据

停止第一个容器:

sudo docker stop mongo-1 

然后再次运行之前的python代码. 可以观察到如下现象:

  1. 即使主节点关了, 代码还是顺利运行
  2. compass 能看到10万条数据.

这说明测试可用性也成功了.

如果此时你登录到第二台容器, 运行mongo 命令. 你会发现这台机器已经成了主节点. 这表示在第一台容器down掉之后, 第二台容器成功地挑起了重担.

测试数据丢失

(为了观察方便, 在compass 里将之前的 TestUser 删掉.)

先将第一台容器重新启动:

sudo docker restart mongo-1

(此时, 此容器已经成了从节点)

步骤:

  1. 用python插入 500 万数据
  2. 插入途中停止主节点容器
  3. 看看程序的反应如何?
  4. 5秒后, 重新启动"主节点"容器(重启之后, 它其实变成了从节点)
  5. 程序运行完之后, 检查 compass 到底插入了多少数据
  6. 分别进入第一个, 第二个容器, 看看他们的数据是否有差值?

我们期望的结果:

  1. 插入过程不能停. (这个已经验证过了)
  2. 看看数据是否有丢失?

(这些过程你自己可以试试)

我的测试结果

查询插入时间: 38 秒

compass 查询结果: 500万数据 (没有丢失!!)

主节点容器数据: 500万. (用 db.TestUser.count() 查总数)

从节点容器运行查询语句的时候报这个错:

image-20210728160330556

这个错误的意思是从节点不可读. 在之前搭建集群的时候, 我们要在从节点这样设置:

db.getMongo().setSecondaryOk()

这表明, 当某个节点down掉再重连之后, 它会恢复成mongodb 的默认从节点配置, 没事, 再次运行这句就是了. 比起数据没有丢失, 这不算多大的事吧?

至此, mongodb集群的搭建, 测试就算彻底完成了.

附录

修改mongodb 密码

为了安装方便, 密码都使用 123456 这样的弱密码. 在安装好集群之后, 我们应该将它改掉.

我向你推荐 pwgen , 用这个小工具来生成密码:

sudo apt install pwgen
pwgen -s 20

登录主节点容器, 使用 db.changeUserPassword 来修改密码:

sudo docker exec -it mongo-1 bash

use admin
db.auth('admin', '123456')

# 修改密码, 假设你的是 xxxyyy
db.changeUserPassword('admin','xxxyyy')

防止日志文件过大

mongodb的日志膨胀非常快, 单个文件非常大, 可以通过这个命令来设置:

db.adminCommand({logRotate:1})

之后日志就会按日期分割成独立的文件. 一些过期的日志, 删了即可.

docker 便捷命令

查看正在运行的容器

sudo docker ps

查看创建没有启动的容器

sudo docker ps -a

一键停止所有容器

sudo docker ps -q |xargs sudo docker stop 

删除全部容器

sudo docker ps -aq |xargs sudo docker rm 

springboot 配置

spring:
  data:
    mongodb:
      uri: mongodb://test:[email protected]:30001,127.0.0.1:30002,127.0.0.1:30003/ExampleDb?authSource=test&replicaSet=MongoSet

作者简介

艺名小肥爬爬(小肥耙耙/小肥巴巴), 一个喜欢阅读/写字/健身/踢球/吉他的程序员, 他和小田园犬肥花在深圳愉快地生活.

欢迎探讨技术领域的方方面面, 你可以在, gitee和知乎找到他:

: https://www.jianshu.com/u/db796a501972

gitee: https://gitee.com/xiaofeipapa

知乎: https://www.zhihu.com/people/chen-yun-shi-75

csdn(不常用): https://blog.csdn.net/m0_46322443

参考文章&感谢

https://blog.csdn.net/lzkIT/article/details/8146567

https://blog.csdn.net/zhanngle/article/details/105132527

https://www.cnblogs.com/zqyx/p/10169820.html

你可能感兴趣的:(搭建测试mongodb副本集)