mongDB复制集搭建及使用

1.简介

Mongodb复制集由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写入Primary,Secondary从Primary同步写入的数据,以保持复制集内所有成员存储相同的数据集,提供数据的高可用。
  下图是一个典型的Mongdb复制集,包含一个Primary节点和2个Secondary节点
  在这里插入图片描述
  从上图可以看出,所有的读写请求都是由客户端应用程序通过驱动来指向MongoDB数据库,写请求都是指向当前数据库的主节点,写请求执行完毕后,会记录在主节点的oplog中(记录写操作而不记录读操作),从节点通过主节点的oplog来进行复制操作。在默认情况下,读请求也是指向主节点的。因为MongoDB复制集是异步复制形式,会由于磁盘的刷盘效率和网络的原因导致从节点的数据相对于主节点有一点延迟,驱动在没有配置的情况下会指向主库,也就是当前最新的数据。当然如果对数据的时效性要求不高时可以配置读操作指向某一个从节点,实现读写分离
  
  复制集特点

  • MongoDB复制集的主是唯一的,但不是固定的。整个复制集中只有一个主节点,其余为从节点或选举节点,但是因为MongoDB具有自动容灾的功能,所以当唯一的主节点发生宕机时会从从节点的Priority参数不为0当中选举一个为主节点,所以说主是唯一的,但不是固定的
  • 当主节点出故障时,是否能选举出新的主节点,并不是由复制集中投票节点存在与否来决定的,而是由当前复制集成员存活数量来决定的。当存活节点小于等于二分之一时,将全部降为从节点,只可读不可写
  • 从库无法写入

2.liunx下搭建复制集(阿里云centos8.1)

  • 打开mongoDB官网https://www.mongodb.com/download-center/community

  • 选择合适的版本
    在这里插入图片描述
    由于我只有一台阿里云的centos8的系统,因此只能选择linux-64位通用版。

  • 登陆linux,创建文件夹/root/mongo-server/,进入该目录下

  • 输入下载命令wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.17.tgz

  • 在当前目录下创建配置文件目录、数据存储目录、日志目录(名称分别为config、data、logs)

  • 解压包到当前文件夹下tar -zxvf linux/mongodb-linux-x86_64-4.0.17.tgz

  • 进入config文件下建立1-repl 文件夹,并进入1-repl文件夹下

  • 在当前目录创建(1-mongo.conf,2-mongo.conf,3-mongo.conf)三份配置文件

  • 进入1-mongo.conf下(vim 1-mongo.conf)输入如下内容,并保存退出

     # 以守护进程的方式运行MongoDB,创建服务器进程
     fork=true
     #数据库配置路径
     dbpath=/root/mongo-server/data/1-repl/db1
     #日志文件配置
     logpath=/root/mongo-server/logs/1-repl/1-mongo.log
     #ip绑定,限制ip访问
     bind_ip=0.0.0.0
     #端口
     port=27011
     #设置日志为追加的方式写日志
     logappend=true
     #启用身份认证
     #auth=true
     #复制集名称
     replSet=repl_1
     #文件以小块存储
     smallfiles=true
     #开启shard分片存储
     #shardsvr=true
    
  • 进入2-mongo.conf下(vim 2-mongo.conf)输入如下内容,并保存退出

     # 以守护进程的方式运行MongoDB,创建服务器进程
     fork=true
     #数据库配置路径
     dbpath=/root/mongo-server/data/1-repl/db1
     #日志文件配置
     logpath=/root/mongo-server/logs/1-repl/1-mongo.log
     #ip绑定,限制ip访问
     bind_ip=0.0.0.0
     #端口
     port=27012
     #设置日志为追加的方式写日志
     logappend=true
     #启用身份认证
     #auth=true
     #复制集名称
     replSet=repl_1
     #文件以小块存储
     smallfiles=true
     #开启shard分片存储
     #shardsvr=true
    
  • 进入3-mongo.conf下(vim 3-mongo.conf)输入如下内容,并保存退出

     # 以守护进程的方式运行MongoDB,创建服务器进程
     fork=true
     #数据库配置路径
     dbpath=/root/mongo-server/data/1-repl/db1
     #日志文件配置
     logpath=/root/mongo-server/logs/1-repl/1-mongo.log
     #ip绑定,限制ip访问
     bind_ip=0.0.0.0
     #端口
     port=27013
     #设置日志为追加的方式写日志
     logappend=true
     #启用身份认证
     #auth=true
     #复制集名称
     replSet=repl_1
     #文件以小块存储
     smallfiles=true
     #开启shard分片存储
     #shardsvr=true
    

.

  • 回退并进入解压的mongoDB的bin目录下

在这里插入图片描述

  • 依次启动3份mongo配置

     ./mongod -config /root/mongo-server/config/1-repl/1-mongo.conf
     ./mongod -config /root/mongo-server/config/1-repl/2-mongo.conf
     ./mongod -config /root/mongo-server/config/1-repl/3-mongo.conf
    
  • 待3个实例启动完成后,进入第一个实例(./mongo 127.0.0.1:27011),复制如下代码

     var rsconfig= {"_id":"repl_1",
       "members":[
       {"_id":1,host:"127.0.0.1:27011"},
       {"_id":2,host:"127.0.0.1:27012"},
       {"_id":3,host:"127.0.0.1:27013"}
       ]
     };
     rs.initiate(rsconfig);
    

其中第一个“_id”为复制集的ID标识,我们在配置文件中已经指定了不能更改。members._id表示成员标记。
这样我们就搭建完成了一个mongoDB复制集。
如果我们检测到复制集中某个节点挂了,只需要重启即可

其他常用命令

  • 查看复制集当前状态rs.status()

在这里插入图片描述

  • 开启从库可读rs.slaveOk()
  • 新增加节点rs.add(“ip:port”)
  • 移除节点rs.remove(“ip;port”)
  • 查看复制集配置rs.conf()

java连接mongoDB复制集

由于MongoDB复制集里Primary节点是不固定的,当遇到复制集轮转升级、Primary宕机、网络分区等场景时,复制集可能会选举出一个新的Primary,而原来的Primary则会降级为Secondary,即发生主备切换

当连接复制集时,如果直接指定Primary的地址来连接,当时可能可以正确读写数据的,但一旦复制集发生主备切换,你连接的Primary会降级为Secondary,你将无法继续执行写操作,这将严重影响到你的线上服务。

要正确连接复制集,需要先了解下MongoDB的Connection String URI所有官方的driver都支持以Connection String的方式来连接MongoDB。

mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]

  • mongodb:// 前缀,代表这是一个Connection String
  • username:password@ 如果启用了鉴权,需要指定用户密码
  • hostX:portX 复制集成员的ip:port信息,多个成员以逗号分割
  • /database 鉴权时,用户帐号所属的数据库
  • ?options 指定额外的连接选项

以连接AliCloudDB for MongoDB为例,当你购买阿里云MongoDB复制集时,就会得到复制集的名称、以及复制集成员的地址信息。

mongodb://root:****@dds-bp114e3f1fc441342.mongodb.rds.aliyuncs.com:3717,dds-bp114e3f1fc441341.mongodb.rds.aliyuncs.com:3717/admin?replicaSet=mgset-677201

通过java来连接mongoDB:

MongoClientURI connectionString = new MongoClientURI("mongodb://root:****@dds-bp114e3f1fc441342.mongodb.rds.aliyuncs.com:3717,dds-bp114e3f1fc441341.mongodb.rds.aliyuncs.com:3717/admin?replicaSet=mgset-677201"); // ****替换为root密码
MongoClient client = new MongoClient(connectionString);
MongoDatabase database = client.getDatabase("mydb");
MongoCollection<Document> collection = database.getCollection("mycoll");

常用连接参数

  • 读写分离

在options里添加readPreference=secondaryPreferred即可实现,读请求优先到Secondary节点,从而实现读写分离的功能,更多读选项参考Read preferences

  • 如何保证数据写入到大多数节点后才返回?

在options里添加w= majority即可保证写请求成功写入大多数节点才向客户端确认,更多写选项参考Write Concern

  • 如何限制连接数
    在options里添加maxPoolSize=xx即可将客户端连接池限制在xx以内

springboot 连接 mongodb复制集例子

spring: 
  data:
    mongodb:
      uri: mongodb://root:password@92.168.1.51:27017,192.168.1.52:27017,192.168.1.53:27017/testdb?replicaSet=myRepl&authSource=admin&readPreference=secondaryPreferred&w=majority

简单拆分一下uri说明:

  • mongodb://root:password@92.168.1.51:27017,192.168.1.52:27017,192.168.1.53:27017/testdb
    这句话表示使用账号root密码为password的账户连接51,52,53这3台mongoDB集群的testdb数据库
  • replicaSet=myRepl&authSource=admin&readPreference=secondaryPreferred&w=majority
    这些参数分别表示复制集名字为myRepl,校验账号和密码使用admin数据库,读数据走读库,当写入数据时等待大多数都写入完成后再返回

更详细的配置

private String user;
private String database; 
private char[] password;

 MongoCredential credential = MongoCredential.createCredential(user, database, password);
 MongoClientOptions options = MongoClientOptions.builder().minSize(20).build();
 List<> list = Arrays.asList(new ServerAddress("host1", 27017),new ServerAddress("host2", 27017))
 MongoClient mongoClient = new MongoClient(list, Arrays.asList(credential), options);
 // 使用uri字符串连接也可以
 // MongoClientURI uri = new MongoClientURI("mongodb://user1:pwd1@host1/?authSource=db1&ssl=true");
// MongoClient mongoClient = new MongoClient(uri);

builder默认配置

public static class Builder {
        private String description;
        private String applicationName;
        //读取偏好, 这里默认的是从主节点读取.
        private ReadPreference readPreference = ReadPreference.primary();
        //使用服务器默认的写关注?
        private WriteConcern writeConcern = WriteConcern.ACKNOWLEDGED;
        //使用服务的默认读关注,默认是local
        private ReadConcern readConcern = ReadConcern.DEFAULT;
        private CodecRegistry codecRegistry = MongoClient.getDefaultCodecRegistry();
        private final List<CommandListener> commandListeners = new ArrayList<CommandListener>();
        private final List<ClusterListener> clusterListeners = new ArrayList<ClusterListener>();
        private final List<ServerListener> serverListeners = new ArrayList<ServerListener>();
        private final List<ServerMonitorListener> serverMonitorListeners = new ArrayList<ServerMonitorListener>();

        private int minConnectionsPerHost;
        private int maxConnectionsPerHost = 100;
        private int threadsAllowedToBlockForConnectionMultiplier = 5;
        //设置服务器选择超时(以毫秒为单位),它定义驱动程序在抛出异常之前等待服务器选择成功的时间
        //值为0表示如果没有可用的服务器,它将立即超时。 负值意味着无限期等待
        private int serverSelectionTimeout = 1000 * 30;
        //线程等待连接变为可用的最长时间
        private int maxWaitTime = 1000 * 60 * 2;
        // 线程池中连接的最大空闲时间
        private int maxConnectionIdleTime;
        private int maxConnectionLifeTime;
        //连接超时时间,必须大于0
        private int connectTimeout = 1000 * 10;
        //socket超时时间
        private int socketTimeout = 0;
        //socket是否保活
        private boolean socketKeepAlive = false;
        private boolean sslEnabled = false;
        private boolean sslInvalidHostNameAllowed = false;
        private boolean alwaysUseMBeans = false;
        //设置心跳频率。 这是驱动程序将尝试确定群集中每个服务器的当前状态的频率。 默认值为10,000毫秒
        private int heartbeatFrequency = 10000;
        //设置最小心跳频率。 如果驱动程序必须经常重新检查服务器的可用性,它将至少在上一次检查后等待很长时间,以避免浪费精力。 默认值为500毫秒。
        private int minHeartbeatFrequency = 500;
        //设置用于集群心跳的连接的连接超时
        private int heartbeatConnectTimeout = 20000;
        //设置用于集群心跳的连接的套接字超时
        private int heartbeatSocketTimeout = 20000;
        //本地阈值
        private int localThreshold = 15;

        private String requiredReplicaSetName;
        private DBDecoderFactory dbDecoderFactory = DefaultDBDecoder.FACTORY;
        private DBEncoderFactory dbEncoderFactory = DefaultDBEncoder.FACTORY;
        private SocketFactory socketFactory;
        private boolean cursorFinalizerEnabled = true;
...}

参考文献:

  1. Java 连接MongoDB集群的几种方式
  2. mongodb连接配置实践
  3. MongoDB复制集原理、搭建及复制集简单维护
  4. MongoDB使用账号密码连接
  5. 关于MongoDB连接字符串URI格式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值