复制集
架构
原理
复制集的选举
触发选举的条件
- 主节点与副节点心跳请求超时
- 复制集初始化
- 新节点加入复制集(因为有可能是故障主节点复活的情况)
选举过程
每个节点都维护一个选举计数器,每个节点的计数器的值都应该是相等的,复制集中最多可以有7个投票节点,从而减少选举所带来的性能消耗
- 当主节点故障时,其中一个副节点(优先级最高,数据最完整的副节点)发起选举请求,将自己的选举计数器加一,并给自己投一票
- 其他可投票节点收到投票请求时,先同步选举计数器,并返回投票结果(未返回投票结果按照反对算)
- 相对候选节点投票节点的数据完整性更高,返回反对
- 相对候选节点投票节点的数据完整性更低,返回赞成
- 若超过半数同意票,候选节点就升级为主节点,否则其他节点就会再发起选举请求
还有一种特殊情况,就是当复制集中只剩下一个主节点时,该主节点会主动降级为副节点
数据同步
初始同步
- 全新节点(不包括复活节点)加入复制集中时,肯定会成为副节点,首先这个新节点会清空所有数据
- 将主节点中的所有数据进行拷贝,在进行拷贝的过程中主节点可能还在更新数据
- 新更新的数据记录通过写库记录进行同步
写库记录同步
主节点的数据更新记录会保存在自己的local.oplog.rs
集合中,副节点将数据更新记录批量复制到自己的local.oplog.rs
集合中,然后再使用这些更新记录进行更新操作
- 写库记录中的日志记录的重复使用,不会导致数据更新错误,比如:主节点对某数据进行加一操作,该日志记录是记录的加一后的值,而不是操作,所以重复的使用这个记录不会导致数据更新错误
- 为了保证写库记录可以重复使用,在批量更新时,会为每条文档的更新增加一条写库记录,所以可能导致写库记录集合容量大于数据容量
- 多线程分批次使用这些日志记录,从而提高同步的效率
实现方式
服务端
- 增加以下配置信息并启动
replication:
replSetName: myset
replication
:复制集replSetName
:指定复制集的名字,同一复制集的名字应该相同
- 连接任意一个节点,初始化复制集,执行以下命令
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 //只作为投票机
}
]
}
)
- 此时从节点是不可读的,想要在从节点上执行读操作,需要在从节点上执行
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创建连接对象
Comments NOTHING