如果不了解 MongoDB Sharded Cluster 原理,请先阅读
关于 sharding 迁移,会分3个部分来介绍,本文为第二部分
- 负载均衡及迁移策略
- chunk 迁移流程
- Balancer 运维管理
moveChunk 命令
从MongoDB sharding迁移那些事(一) 我们了解到,Chunk 迁移可能是 Balancer 触发,也可能用户手动向 mongos 发送 moveChunk
命令来触发。
我们先来近距离了解下mongos 上的 moveChunk 命令,如果是 Balancer 触发,其逻辑也跟 moveChunk
里类似。
moveChunk的主要参数列表如下
参数 | 含义 |
---|---|
moveChunk | 指定namespace(集合名) |
find | 通过查询条件来指定要迁移的 chunk |
bound | 通过上下限来指定要迁移的 chunk,上下限必须要跟 chunk 的范围完全匹配 |
to | 迁移目标 shard 名 |
归根结底就是要指定『迁移哪个集合的哪个 chunk』,『把这个 chunk 迁移到哪个 shard』,选择 chunk 时,可以通过 find 或 bound 2种方式来指定(两者只能选择一个),mongos 就能计算出要迁移哪个 chunk,并知道 chunk 所在的源 shard。
mongos 接下来会构造根据上述参数,向源 shard 发送一个 moveChunk 命令(mongos 和 shard 都支持 moveChunk
这个命令,但内部的实现逻辑不同),接下来所有的迁移工作就由源 shard 接受了,等迁移完全结束,向 mongos 反馈执行结果。
迁移步骤
Step1: mongos 发送 moveChunk 给源 shard
mongos 接受到用户发送的迁移 chunk 命令,或者因负载均衡策略需要迁移 chunk,会构建一个 moveChunk
的命令,并发送给源 shard。
Step2:源 shard 通知目标 shard 开始同步 chunk数据
源 shard 收到 mongos 发送的 moveChunk 命令后,会向目标 shard 发送 _recvChunkStart
的命令,通知目标 shard 开始迁移数据(真正的数据迁移由目标shard 主动发起)。接下来,源 shard 会记录该 chunk 在迁移过程中的所有增量修改操作。
Step3: 目标 shard 同步 chunk 数据到本地
目标 shard 接受到 _recvChunkStart
命令后,就会启动单独的线程来读取 chunk 数据并写到本地,主要步骤包括:
- 目标 shard 创建集合及索引(如果有必要)
- 如果迁移的集合在目标 shard 上没有任何 chunk,则需要先在目标 shard 上创建集
合,并创建跟源 shard 上集合相同的索引
- 如果迁移的集合在目标 shard 上没有任何 chunk,则需要先在目标 shard 上创建集
- 目标 shard 清理脏数据 (如果有必要)
- 如果目标 shard 上已经存在该 chunk 范围内的数据,则肯定为某次迁移失败导致的脏数据,先将这些数据清理掉。
- 目标 shard 向源 shard 发送
_migrateClone
命令读取 chunk 范围内的所有文档并写入到本地,即迁移 chunk 全量数据,迁移完后更新状态为 STEADY(可以理解为全量迁移完成的状态)。 - 源 shard 会不断调用查询目标 shard 上的迁移状态,看是否为 STEADY 状态,如果已经是 STEADY 状态,就会停止源 shard 上的写操作(通过对集合加互斥写锁实现)。接下来发送
_recvChunkCommit
告诉目标 shard 不会再有新的写入了。 - 目标 shard 的迁移线程不断向源 shard 发送
_transferMods
命令,读取迁移过程中的增量修改,并应用到本地,增量迁移完成后,向源确认_recvChunkCommit
的结果。 - 源 shard 收到
_recvChunkCommit
的结果,整个数据迁移的步骤完成。
Step4:源 shard 更新 config server 元数据
数据迁移完成后,源 shard 就会向 config server 更新 chunk 对应的 shard 信息,同时也会更新 chunk 的版本信息,这样 mongos 发现本地版本更低就会主动的 reload 元数据,具体机制参考 MongoDB Sharded Cluster 路由策略。
Step5:源 shard 删除 chunk 数据
chunk 迁移到目标 shard 后,源上的 chunk 就没有必要再保存了,源 shard 会将 chunk 数据删除,默认情况下源 shard 会将删除操作加入到队列,异步删除,如果 moveChunk 时,指定了 _waitForDelete 参数为 true,则同步删除完再返回。
–
2016-09-28 11:35:47 update
一旦源shard 查询到目标 shard 进入到 STEADY 状态了,源 shard 就会进入临界区,测试源上的写就会排队等待。等整个迁移完了,这些等待的写操作就会继续执行,但此时 chunk 的版本号已经更新了,会告诉客户端版本过低,客户端重新从 config server 读取配置,此时拿到的路由信息里 chunk 已经在目标 shard 了,然后写会发往目标 shard 。
总结
本文粗略的介绍了 chunk 迁移的主要流程,chunk 的迁移会受 Balancer 策略、chunkSize等很多因素影响,第三部分将会介绍迁移相关的运维管理,以便大家更好的管理 MongoDB Sharded Cluster。