mongodb 复制集

复制集的一些注意事项

复制集的作用

MongoDB 复制集的主要意义在于实观服务高可用,它的现实依赖于两个方面的功能:

数据写入时将数据迅速复制到另一个独立节点上
在接受写入的节点发生故障时自动选举出一个新的替代节点
在实现高可用的同时,复制集实现了其他几个附加作用:

数据分发:将数据从一个区域复制到另一个区域,减少另一个区域的读延迟
读写分离:不同类型的压力分别在不同的节点上执行 
异地容灾:在数据中心故障时候快速切换到异地

复制集结构

PSS:一主两从									生产环境中,pss居多,psa 会有一些弊端;
PAS:一主一从 一个投票节点


一个典型的复制集由 3 个以上具有投票权的节点组成,
包括:
  一个主节点(PRIMARY):接受写入操作和选举时投票
  两个(或多个)从节点(SECONDARY):复制主节点上的新数据和选举时投票 
  Arbiter(投票节点)

数据是如何复制的


当一个修改操作,无论是插入、更新或删除,到达主节点时,它对数据的操作将被记录下来(经过一些必要的转换),这些记录称为 oplog.

从节点通过在主节点上打开一个 tailable 游标不断获取新进入主节点的 oplog,并在自己的数据上回放,以此保持跟主节点的数据一致。

image-20220829175345087

通过选举完成故障转移

具有投票权的节点之间两两互相发送心跳;
当 5 次心跳未收到时判断为节点失联;
如果失联的是主节点,从节点会发起选举,选出新的主节点;
如果失联的是从节点则不会产生新的选举;
选举基于 RAFT 一致性算法实现,选举成功的必要条件是大多数投票节点存活;

image-20220829175521453

影响选举的因素

整个集群必须有大多数节点存活;被选举为主节点的节点必须:
·能够与多数节点建立连接 
·具有较新的 oplog
·具有较高的优先级(如果有配置)

常见选项

复制集节点有以下常见的选配项:
·是否具有投票权(v 参数):有则参与投票;
·优先级(priority 参数):优先级越高的节点越优先成为主节点。优先级为 0 的节点无法成为主节点;
·隐藏(hidden 参数):复制数据,但对应用不可见。隐藏节点可以具有投票仅,但优先级必须为 O; 
·延迟(slaveDelay 参数):复制 n 秒之前的数据,保持与主节点的时间差。

image-20220829175840116

复制集注意事项

·关于硬件:
    ·因为正常的复制集节点都有可能成为主节点,它们的地位是一样的,因此硬件配置上必须一致;
    ·为了保证节点不会同时宿机,各节点使用的硬件必须具有独立性。
·关于软件:
    ·复制集各节点软件版本必须一致,以避免出现不可预知的问题。
·增加节点不会增加系统写性能!

默认从节点没有读权限,如果修改为了读权限,默认是强制读,没有写权限;
一旦作为一个节点的从库,就不可以再作为另外一个节点的从库;

复制集配置

a.规划

三个以上节点或者多实例
多实例:
1.多个端口:28017、28018、28019、28020
2.多套目录
su - mongod
mkdir -p /mongodb/{28017..28020}/{data,log}

3.配置文件
# https://raw.githubusercontent.com/mongodb/mongo/3a848e239082625f1f1e6c677f149412654f53b6/rpm/mongod.conf
cat > /mongodb/28017/mongod.conf <<EOF
# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /mongodb/28017/log/mongodb.log

# Where and how to store data.
storage:
  journal:
    enabled: true
  dbPath: /mongodb/28017/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true

# how the process runs
processManagement:
  fork: true  # fork and run in background
  timeZoneInfo: /usr/share/zoneinfo

# network interfaces
net:
  port: 28017
  bindIp: 127.0.0.1,10.23.5.242  # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.

#security:

#operationProfiling:

replication:
  oplogSizeMB: 2048
  replSetName: my_rep

#sharding:

## Enterprise-Only Options

#auditLog:
EOF

cp /mongodb/28017/mongod.conf /mongodb/28018/
cp /mongodb/28017/mongod.conf /mongodb/28019/
cp /mongodb/28017/mongod.conf /mongodb/28020/

sed -i 's#28017#28018#g' /mongodb/28018/mongod.conf
sed -i 's#28017#28019#g' /mongodb/28019/mongod.conf
sed -i 's#28017#28020#g' /mongodb/28020/mongod.conf

# 启动实例
mongod -f /mongodb/28017/mongod.conf
mongod -f /mongodb/28018/mongod.conf
mongod -f /mongodb/28019/mongod.conf
mongod -f /mongodb/28020/mongod.conf


b. 配置复制集

1. 1主2从,从库是普通从库(PSS)
config = {_id: "my_rep", members: [
    												{_id: 0, host: '10.23.5.242:28017'},
    												{_id: 1, host: '10.23.5.242:28018'},
    												{_id: 2, host: '10.23.5.242:28019'}
]}

rs.initiate(config)

2. 1主1从1个arbiter(PSA)
config = {_id: "my_rep", members: [
    												{_id: 0, host: '10.23.5.242:28017'},
    												{_id: 1, host: '10.23.5.242:28018'},
    												{_id: 2, host: '10.23.5.242:28019', "arbiterOnly": true}
]}

rs.initiate(config)

c. 复制测试

my_rep:PRIMARY> db.movies.insert([ {"title": "Jaws", "year": 1975, "imdb_rating": 8.1},
... {"title": "batman", "year": 1985, "imdb_rating": 7.6 },
... ]);
BulkWriteResult({
    "writeErrors" : [ ],
    "writeConcernErrors" : [ ],
    "nInserted" : 2,
    "nUpserted" : 0,
    "nMatched" : 0,
    "nModified" : 0,
    "nRemoved" : 0,
    "upserted" : [ ]
})


// 从库配置读功能;默认mongodb从库没有读功能;
my_rep:SECONDARY> rs.slaveOk()

// 查看插入的数据
my_rep:SECONDARY> db.movies.find()
{ "_id" : ObjectId("630d774f7eca224e1f888695"), "title" : "batman", "year" : 1985, "imdb_rating" : 7.6 }
{ "_id" : ObjectId("630d774f7eca224e1f888694"), "title" : "Jaws", "year" : 1975, "imdb_rating" : 8.1 }

d. 查看复制集状态

// 可以打印当前复制集状态信息;
my_rep:PRIMARY> rs.status()

// 重点看 members
"members" : [
    	{
    		"_id" : 0,
    		"name" : "10.23.5.242:28017",
    		"health" : 1,
    		"state" : 1,
    		"stateStr" : "PRIMARY",
    		"uptime" : 956,
    		"optime" : {				// 日志的版本号
    			"ts" : Timestamp(1661827202, 1),			// 使用ts 的方式记录;1661827202 当前时间戳、1代表在时间戳的这一秒中的第几个操作;
    			"t" : NumberLong(1)
    		},
    		"optimeDate" : ISODate("2022-08-30T02:40:02Z"),
    		"syncingTo" : "",
    		"syncSourceHost" : "",
    		"syncSourceId" : -1,
    		"infoMessage" : "",
    		"electionTime" : Timestamp(1661826682, 1),
    		"electionDate" : ISODate("2022-08-30T02:31:22Z"),
    		"configVersion" : 1,
    		"self" : true,
    		"lastHeartbeatMessage" : ""
    	},
    	....
    	
    	

rs.isMaster()			// 查看是否是主节点


2. 添加删除节点
rs.add("ip:port");   // 新增从节点
rs.addArb("ip:port"); 		// 新增仲裁节点
rs.remove("ip:port");			// 删除一个节点


3. 特殊从节点的配置
- 优先级(priority 参数:0-100)
    优先级越高的从节点越优先成为主节点;
    优先级为0的节点无法成为主节点;
- 隐藏(hidden参数):复制数据,但对应用不可见。隐藏节点可以具有投票权,但优先级必须为0;
- 延迟(slaveDelay参数):复制n秒之前的数据,保持与主节点的时间差。

配置延迟节点(一般延迟节点也配置成 hidden)
cfg=rs.conf()						// 将 rs.conf() 导入到变量 cfg中
cfg.members[1].priority=0 			// 修改其中的字段 priority ,将其改为0;优先级;members[1] 列表索引,代表具体节点;列表索引从 0 开始,依次往后排,
cfg.members[1].slaveDelay=120 	// 修改字段 slaveDelay ,将其改为 120;与主节点时间差,延迟复制
cfg.members[1].hidden=true			// 修改字段 hidden ,将其改为 true;是否隐藏
cfg.members[1].votes=0
rs.reconfig(cfg)				// 重新配置

改回来:
cfg=rs.conf()
cfg.members[2].priority=1
cfg.members[2].slaveDelay=0
cfg.members[2].hidden=0
cfg.members[2].votes=0
rs.reconfig(cfg)

配置成功后,通过以下命令查询配置后的属性 
rs.conf();

e.副本集其他操作命令

-查看副本集的配置信息 
admin> rs.config()

-查看副本集各成员的状态 
admin> rs.status()

-一副本集角色切换(不要人为顺便操作,有风险)
admin> rs.stepDown()
注:
admin> rs.freeze(300)  //锁定从,使其不会转变成主库; 主从切换时可以使用;锁定该从,使其切换到别的从库
freeze() 和 stepDown 单位都是秒。

-一设置副本节点可读:在副本节点执行 
admin> rs.slaveok()

eg:
admin> use app
app> db.createCollection('a')


--查看副本节点信息
admin> rs.printSlaveReplicationInfo()
source:192.168.1.22:27017
    		syncedTo: Thu May 26 2016 10: 28: 56 GMT+0800  (CST) 
    		0 secs  (o hrs) behind the primary  // 这是延时信息;