单数据量大或者吞吐量大到一定程度的时候,一个服务器已经无法支撑了——频繁的查询会耗尽CPU资源、不断增多的数据会耗尽硬盘空间、不断增大的工作空间(包括索引)会耗尽内存最终导致虚拟内存(磁盘)的使用、等等。解决的方法就是把数据分布到多个不同的服务器中,如下图所示。
具体的实现:MongoDB通过下图所示的分片集群的方法实现:
其中:
- Shard:存储数据的一个分片。可以是一个mongod实例、或一个replica set(生产环境中)。
- Query Router(mongos):提供给客户端操作MongoDB cluster的接口。一个cluster可以有多个mongos。它缓存了Config Server中的路由数据(metadata),当数据有更新时缓存会被刷新。一般和客户端部署在同一个服务器上。
- Config Server:保存数据分片规则(对应关系)的元数据(metadata),mongos使用这些配置数据来访问具体的某个shard。从3.2版本开始,Config Server可以是一个replica set。
数据分片的方法:
- 按照连续的一个区间分片:
- 优点:对应区间查询,可以在一个shard中命中,提高效率
- 缺点:数据分片可能很不均衡
- 哈希分片:
- 优点:数据分片很均匀
- 缺点:对于区间查询,效率不高
维持各个分片的数据均衡:
MongoDB会启动两个后台进程来维持各个分片之间的数据均衡。重新均衡的同时,需要更新Config Server中的metadata,以便Router可以正确路由读写请求。
- Splitter:这个进程把一个shard中的数据分块(chunk,缺省是64M/chunk),如果一个chunk增长到超过最大值,新的insert或update操作会触发分块,如下图所示:
- Balancer:这个进程用于维持各个shard中的chunk个数均衡,如果不均衡(Splitter分块之后,会导致不均衡),它就从个数多的shard中移动一些到个数少的shard中,如下图所示:
新增一个shard的时候,balancer就会开始迁移一些chunk过去;删除一个shard的时候,balancer会把这个shard中的所有chunk迁移到其他shard中,迁移结束后就可以安全的移除这个shard了。
把一个正在使用的Stand-alone的replica set 升级转换成一个分片集群的具体步骤:
相反地,把一个分片聚群转为一个Stand-alone的replica set的步骤: