七 创建副本
副本
使用复制把数据副本保存到多台服务器上。
副本集是一组服务器,其中有一个主服务器,用于处理客户端请求;还有多个备份服务器用于保存数据副本。如果主服务器崩溃,备份服务器回自动其中一台位新的主服务器。
创建副本集
启动shell但是不连接到任何mongod。
1 | mongo --nodb |
笔者这里使用的是windows10的cmd可以正常执行成功。如果在windows下使用cmder,不知道为啥会报错。
1 | // 创建副本集,这里原书中没有指定name字段,会导致后面两句话执行不成功,所以这里根据报错猜测原因,加入了name字段 |
现在分别有了三个进程,运行在被分配的三个端口中。这三个端口怎么找呢?就在执行完第一行代码之后,控制台会返回一堆信息,其中接近是最底下的地方那里有个字段叫ports,就是那个。
把这个shell搁置在一旁,然后新启一个shell:
1 | conn1 = new Mongo('localhost:20000') |
返回一个dict(js里是这么叫吗。。),其中hosts列表表示该副本集的所有端口,ismaster表示是不是主节点,primary字段表示主节点端口。
由于备份节点的数据可能会落后于主节点,所以备份节点一般是拒绝读取请求的,如果在备份节点上做查询,会得到一个错误提示。
如果真想访问备份服务器,敲
1 | conn1.setSlaveOk() |
最后,关闭副本集
1 | replicaSet.stopSet() |
自动故障转移
现在尝试关闭主节点,应该会看到其中一个备份节点会升级为主节点。
1 | primaryDB.adminCommand({'shutdown': 1}) |
之后对第二个链接调用idMaster函数可以看到它已经变为主节点。
配置副本集
上一节是在自己的localhost上面尝试建立测试用的一个副本集,现在来看假如有三台linux机器,怎么在其上搭建副本集。
假设我们所在的机器是server-1,另有两台机器是server-2和server-3。
1 | on local machine(server-1) |
为了让三个mongod知道彼此的存在,需要设置。shell中键入:
1 | config = { |
注意,上面的spock是集合的名字,不要再傻傻去查翻译了。
之后对主节点进行初始化。
1 | db = (new Mongo('server-1:27017')).getDB('test') |
其中rs这个变量是个全局变量,包含与复制相关的辅助函数。
需要确保每台机器可以连接到其他机器。
允许所有节点都在同一台机子上。
修改副本集配置
添加成员和移除成员
1 | // 增加 |
做remove操作的时候会在控制台打印很多错误信息,这很正常。
每次更新配置之后rs.config()
返回的version字段都会加一。
假设要直接更改config表:
1 | var config = rs.config() |
直接改。
主节点选举机制
太长不看。
下面讲副本集的组成。
同步
MongoDB的复制功能是使用操作日志oplog实现的,这份日志包含了主节点的每次写操作。oplog是主节点local数据库中的一个固定结合。
备份节点同样也拥有一份oplog。在执行完主节点的oplog之后,会更新进自己的oplog。为了避免过程中出问题重新执行oplog会重复生效操作,MongoDB执行oplog中的同一操作,只会执行一次。
通常来说每个写操作只影响一个文档,只会产生一条oplog日志。但是如果是执行像db.coll.remove()这种操作,就会产生多条数据(条数与coll中文档个数相当)
初始化同步
副本集中的成员启动之后,会检查是否能从某个成员那里进行同步(增量),如果不行,那么会从另一个成员那里进行完整的数据复制(全量)。这就是初始化同步的过程。
具体步骤如下:
- 删除自身所有的数据库
- 选择一个同步源,克隆数据
- 检查是否有文档需要重新克隆,重新克隆克隆过程中发生改动的文档,这是第一个oplog步骤
- 记录上一个步骤的oplog
- 创建索引
- 将创建索引时的oplog同步
- 切换到普通同步状态
处理落后的数据
如果数据落后于同步源台太多,那么这个备份节点就是陈旧的$stale$。
一个陈旧节点会尝试查看其他成员,如果有某个成员的oplog足够详尽,能够让它追上步伐,那就用他的oplog来同步数据。如果找不到这么一台机器,那就需要完全同步。
为了避免完全同步,最好让主节点能够用比较大的oplog,毕竟磁盘不用钱的。
心跳
为了知道副本集的状态,需要每隔2秒向其他成员发出一个心跳请求。最重要的功能之一就是让主节点知道自己是否符合条件,如果不符合就会退化成备份节点。
成员状态
- STARTUP
- STARTUP2
- RECOVERING
- ARBITER
- DOWN
- UNKNOWN
- REMOVED
- ROLLBACK
- FATAL
选举
选举发生时机:其中一个成员无法到达(reach)主节点,它会向自己所有能reach的成员发通知,说希望被选举为主节点。其他节点会进行判断,看那个节点符不符合参与选举的条件(其中有一个原因可能是主节点其实在正常运行)。如果符合选举条件,就会开始选举。
一般而言选举非常快,可能只要几毫秒。运气不好也就几分钟。
回滚
在主节点在写入的时候崩溃之后,会选出新的节点。原主节点恢复之后会尝试同步刚才崩溃那次操作,如果这个操作在新的主节点并不存在,那么原主节点就会回滚。
如果回滚失败(数据量过大),就会进行完全同步。
关于副本集的更多内容在这里不做记录,等成为运维之后再说吧。