调研:
全量和增量备份:新增节点第一次同步是,是全量备份,以后每次同步就是增量备份
异地配置延迟节点:
简介:延迟节点是过去某个时间点的“数据快照”,通过做数据备份
优点:在主节点上删除数据时,其他从节点实时同步主节点数据,从节点删除也被删除,而此时延迟节点由于延迟时间数据未同步,可以恢复主节点上误删除的数据
缺点:做不到异地容灾
最终方案:
3个节点
数据中心一 数据中心二 数据中心三
primary secondary 仲裁节点
5个节点
数据中心一 数据中心二 数据中心三
primary secondary 仲裁节点
secondary 仲裁节点
异地部署建议:数据中心二的secondary节点指定从secondary复制 ,安全写入级别 w:2 j:true
测试2个数据中心方案
5个节点 2个数据中心
数据中心一 :部署主节点primary 和 从节点 secondary
数据中心二:部署从节点 secondary 和 2个仲裁节点(仲裁节点不暂用资源,不同步数据,只投票)
将一个节点从集群中一处 rs.remove(“172.16.31.146:17017”)
增加集群sencondary节点 rs.add({_id:3,host:“172.16.31.146:17017”,priority:0.5})
增加集群仲裁节点 rs.add({_id:4,host:“172.16.31.146:17017”,arbiterOnly:true})
看集群个节点状态 rs.status()
如上图所示:目前172.21.15.15:17017 为primary
查看集群配置 rs.conf()
将172.21.15.18:17017(secondary)优先级定位0.5
cfg=rs.conf()
cfg.members[2].priority=0.5
rs.reconfig(cfg)
成功如下图
数据中心一:
172.21.15.15:17017(primary) 优先级priority最大,为2,初始化时会最先被选为主节点
172.21.15.17:17017(secondary) 优先级priority次之,为1,当主节点宕机后会被选为主节点
数据中心二:
172.21.15.18:17017(secondary) 优先级priority 为0.5,当数据中心一2台机器宕机后,会被选为主节点
172.16.31.144:17017(arbiterOnly) 优先级priority为0,只投票,不同步数据,不参加选举
172.16.31.146:17017(arbiterOnly) 优先级priority为0,只投票,不同步数据,不参加选举
测试1:当数据中心二三台机器宕机后,是否会重新选举?
关闭数据中心二3台机器
分别切换至18,144,146 三台机器bin目录下执行命令:net stop mongoDB
看数据状态:rs.status()
结论:可见当异地数据中心二3节点宕机后,由于存活的节点不超过半数,导致无法选举,数据中心一的主节点变成只读节点,无法写入。
印证官网对5成员副本集描述: 对于5个成员的副本集,成员的分布可能是:
2个数据中心:3个成员到数据中心1,2个成员到数据中心2
如果数据中心1宕机,复本集将变成只读
如果数据中心2宕机,副本集仍然可写,因为数据中心1的成员可见大多数副本集
测试二:
当数据中心一 primary(172.21.15.15:17017)宕机后,secondary(172.21.15.17:17017)当选为主节点,因为其priority较大
当数据中心一2个节点都宕机后,数据中心二 priority 较大者当选主节点
当数据中心一恢复后:例如172.21.15.17:17017 先恢复,会重新触发选举,172.21.15.17:17017变为主节点(因为其priority=1),然后172.21.15.15:17017(priority=2)恢复后,原先主节点恢复
结论:每当心跳丢失或者心跳恢复都会触发选举,选举成员必须超过集群成员的一半,选举会选取priority较大者为主节点
测试三 :四个节点集群,2个节点一个集群,当其中一个数据中心挂了后,是否能选举
测试过程和结果:
移除集群节点172.16.31.146: 17017
命令:rs.remove(“172.16.31.146:17017”)
数据中心一: primary(172.21.15.15:17017) secondary(172.21.15.17:17017)
数据中心二: secondary(172.21.15.18:17017) arbiterOnly(172.16.31.144:17017)
测试当:数据中心一primary(172.21.15.15:17017)宕机后,由于存活超过半数(剩下节点为数据中心一 secondary(172.21.15.17:17017)和数据中心二: secondary(172.21.15.18:17017) arbiterOnly(172.16.31.144:17017)),所以可以选举,172.21.15.17:17017为主节点
当数据中心一2个节点都宕机后,数据中心二只剩下2个节点,不超过半数,无法选举, secondary(172.21.15.18:17017) 只读
当数据中心二2个节点宕机后,数据中心一数据中心二只剩下2个节点,不超过半数,无法选举, primary(172.21.15.15:17017)变成只读
此方案不可满足需求
测试四:mongoDB集群默认复制方式都是级联复制
即节点A为primary节点,节点B为sencondary节点,正常情况下从节点会以节点的健康状态,最新更新时间>大于自己的更新时间和其他节点到自己的节点ping时间最短来选区的,但是可以人工干预(即会选择一个离自己较近且数据比自己新的节点复制)
测试过程:禁止默认级联复制,人工选择复制方式
禁用:
cfg=rs.conf()
cfg.settings.chainningAllowed=false
rs.reconfig(cfg)
指定secondary 172.21.15.18:17017节点从scondary节点17复制:
rs.syncFrom(“172.21.15.17:17017”)
查看状态:rs.status(),显示成功
若指定的复制的节点宕机,例如将172.21.15.17:17017 net stop mongoDB, 172.21.15.18:17017复制节点会到primary下复制
测试五:效率测试,测试代码如下
public class Mongo {
public static void main(String[] args) {
DBObject user = new BasicDBObject();
user.put(“name”, “david”);
user.put(“age”, 32);
MongoClient mongoClient = new MongoClient(“172.21.15.15”, 17017);
WriteConcern w = new WriteConcern();
w = w.withW(1).withJournal(true);
DB db = mongoClient.getDB(“blog”);
DBCollection collection = db.getCollection(“article”);
collection.setWriteConcern(w);
long timeStart = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
user.put("_id",“5e0ef7fdd657f427c5a8c771”+i);
collection.save(user);
}
long timeBetween = System.currentTimeMillis() - timeStart;
System.out.println(timeBetween);
}
}
以本地 15 为primary 17为本地secondary
异地 144北京虚拟机为异地secondary测试(从17同步数据),146为异地仲裁节点,以下是配置信息
异地 18仲裁节点
MongoDB支持WriteConcern
w:数据写如number个节点才向客户确认
{w:0} 对客户写入不需要发送确认,适用于性能要求高,但不关注正确性
{w:1}默认的writeConcern,数据写入到Primary就像客户端发送确认
{w:‘majority’}数据写入副本集大多数成员猜想客户端发送数据,适用于对数据安全行要求高场景,但是该选项会降低性能
j:写入操作journal持久化后才能向客户端确认
默认为{j:false} 如果要求prima持久化才向客户端确认,则指定该选项为true
以下为java中测试效率,以循环插入5000条数据为例:
总结 :
1.存在异地节点不适合使用majority,网速慢的话会导致写入速度太慢 ,对性能要求非常高建议使用默认w:1 j:false 对速度和安全同样要求,建议使用w:2 j:true
2.若3个非仲裁节点其中宕机一个 {w:3}{j:false} 就只能始终写入一条数据,出现如下报错,无法写入数据,所以不建议将所有节点写上
Updating cluster description to {type=REPLICA_SET, servers=[{address=172.21.15.15:17017, type=REPLICA_SET_PRIMARY, roundTripTime=3.4 ms, state=CONNECTED}]
3.由于本集群只部署一主2从2仲裁,只能写入3个节点,所以写入四个节点报错