09-复制集

nobility 发布于 2022-12-16 1419 次阅读


复制集

架构

复制集

原理

复制集的选举

触发选举的条件
  • 主节点与副节点心跳请求超时
  • 复制集初始化
  • 新节点加入复制集(因为有可能是故障主节点复活的情况)
选举过程

每个节点都维护一个选举计数器,每个节点的计数器的值都应该是相等的,复制集中最多可以有7个投票节点,从而减少选举所带来的性能消耗

  1. 当主节点故障时,其中一个副节点(优先级最高,数据最完整的副节点)发起选举请求,将自己的选举计数器加一,并给自己投一票
  2. 其他可投票节点收到投票请求时,先同步选举计数器,并返回投票结果(未返回投票结果按照反对算)
    • 相对候选节点投票节点的数据完整性更高,返回反对
    • 相对候选节点投票节点的数据完整性更低,返回赞成
  3. 若超过半数同意票,候选节点就升级为主节点,否则其他节点就会再发起选举请求

还有一种特殊情况,就是当复制集中只剩下一个主节点时,该主节点会主动降级为副节点

数据同步

初始同步
  1. 全新节点(不包括复活节点)加入复制集中时,肯定会成为副节点,首先这个新节点会清空所有数据
  2. 将主节点中的所有数据进行拷贝,在进行拷贝的过程中主节点可能还在更新数据
  3. 新更新的数据记录通过写库记录进行同步
写库记录同步

主节点的数据更新记录会保存在自己的local.oplog.rs集合中,副节点将数据更新记录批量复制到自己的local.oplog.rs集合中,然后再使用这些更新记录进行更新操作

  • 写库记录中的日志记录的重复使用,不会导致数据更新错误,比如:主节点对某数据进行加一操作,该日志记录是记录的加一后的值,而不是操作,所以重复的使用这个记录不会导致数据更新错误
  • 为了保证写库记录可以重复使用,在批量更新时,会为每条文档的更新增加一条写库记录,所以可能导致写库记录集合容量大于数据容量
  • 多线程分批次使用这些日志记录,从而提高同步的效率

实现方式

服务端

  1. 增加以下配置信息并启动
replication:
   replSetName: myset
  • replication:复制集
    • replSetName:指定复制集的名字,同一复制集的名字应该相同
  1. 连接任意一个节点,初始化复制集,执行以下命令
rs.initiate(
    {
        _id: "myset",	//指定的复制集名称
        members: [	//添加复制集各个节点地址
            {
                _id: 0,
                host: "127.0.0.1:27018"
            },
            {
                _id: 1,
                host: "127.0.0.1:27019"
            },
            {
                _id: 2,
                host: "127.0.0.1:27020",
                arbiterOnly: true	//只作为投票机
            }
        ]
    }
)
  1. 此时从节点是不可读的,想要在从节点上执行读操作,需要在从节点上执行rs.slaveOk(true)(高版本使用rs.secondaryOk(true)

若想重新修改配置,可以使用JavaScript语法使用rs.config()获取配置对象,进行修改后使用rs.reconfig(config)将刚才修改的配置对象当作参数传入即可

客户端

ArrayList<ServerAddress> ServerAddresses = new ArrayList<>();	//集群节点列表
ServerAddresses.add(new ServerAddress("127.0.0.1", 27017)); //集群节点1 
ServerAddresses.add(new ServerAddress("127.0.0.1", 27018)); //集群节点2
ServerAddresses.add(new ServerAddress("127.0.0.1", 27019)); //集群节点3
MongoClient mongoClient = new MongoClient(ServerAddresses);  //根据地址连接对象,创建连接对象
MongoClientOptions build = new MongoClientOptions.Builder().  //构建配置对象
    connectionsPerHost(10). //每个地址对象的最大连接数
    connectTimeout(10000).  //连接超时时间
    socketTimeout(1000).  //读写操作超时时间
    build();  //构建完毕
ArrayList<ServerAddress> ServerAddresses = new ArrayList<>();	//集群节点列表
ServerAddresses.add(new ServerAddress("127.0.0.1", 27017)); //集群节点1 
ServerAddresses.add(new ServerAddress("127.0.0.1", 27018)); //集群节点2
ServerAddresses.add(new ServerAddress("127.0.0.1", 27019)); //集群节点3
MongoClient mongoClient = new MongoClient(ServerAddresses, build);  //根据所有节点地址和连接配置对象创建连对象
MongoClientURI connectionString = new MongoClientURI("mongodb://127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019");	//创建连接URI
MongoClient mongoClient = new MongoClient(connectionString);	//根据URI创建连接对象
此作者没有提供个人介绍
最后更新于 2022-12-16