107.MongoDB 如何实现分片?

MongoDB 分片,是将数据水平切分到不同的物理节点。当应用数据越来越大的时候,数据量也会越来越大。当数据量增长时,单台机器有可能无法存储数据或可接受的读取写入吞吐量。利用分片技术可以添加更多的机器来应对数据量增加以及读写操作的要求。

或者,我们可以将 MongoDB 分片理解成内置的分库分表功能。

具体如何使用,可以看看 《MongoDB 分片》 文章。

? 我应该启动一个集群分片(sharded)还是一个非分片集群的 MongoDB 环境?

为开发便捷起见,我们建议以非集群分片(unsharded)方式开始一个 MongoDB 环境,除非一台服务器不足以存放你的初始数据集。从非集群分片升级到集群分片(sharding)是无缝的,所以在你的数据集还不是很大的时候没必要考虑集群分片(sharding)。

另外,引入 MongoDB 分片后,会带来相应的运维复杂性,所以在 MongoDB 复制集能够支撑当前业务的情况下,不要过早的使用 MongoDB 分片。

? 分片(Shard)和复制(replication)是怎样工作的?

每一个分片(shard)是一个分区数据的逻辑集合。分片可能由单一服务器或者集群组成,我们推荐为每一个分片(shard)使用集群。

? 数据在什么时候才会扩展到多个分片(Shard)里?

MongoDB 分片是基于区域(range)的。所以一个集合(collection)中的所有的对象都被存放到一个块(chunk)中。只有当存在多余一个块的时候,才会有多个分片获取数据的选项。

现在,每个默认块的大小是 64Mb,所以你需要至少 64 Mb 空间才可以实施一个迁移。

? 当更新一个正在被迁移的块(Chunk)上的文档时会发生什么?

更新操作会立即发生在旧的块(Chunk)上,然后更改才会在所有权转移前复制到新的分片上。

? 如果一个分片(Shard)停止或很慢的时候,发起一个查询会怎样?

如果一个分片停止了,除非查询设置了 “Partial” 选项,否则查询会返回一个错误。如果一个分片响应很慢,MongoDB 会等待它的响应。

? 我可以把 moveChunk 目录里的旧文件删除吗?

没问题,这些文件是在分片(shard)进行均衡操作(balancing)的时候产生的临时文件。一旦这些操作已经完成,相关的临时文件也应该被删除掉。

但目前清理工作是需要手动的,所以请小心地考虑再释放这些文件的空间。

? 如果块移动操作(moveChunk)失败了,我需要手动清除部分转移的文档吗?

不需要,移动操作是一致(consistent)并且是确定性的(deterministic)。

  • 一次失败后,移动操作会不断重试。
  • 当完成后,数据只会出现在新的分片里(shard)。