当MongoDB由于存储的数据越来越多, 由于性能原因, 或者单个主机资源限制, 垂直扩容没有办法进一步的时候, 我们就需要开始考虑水平扩容了。
与垂直扩容不同的是, 水平扩容不需要新添加的机器有多么强大的功能,它的设计理念是将业务数据尽可能平均的划分成一段一段的, 每一段分布在一台机器上, 这样, 当系统需要进一步扩容的时候,只需要添加机器, 将现有数据的一部分迁移到新添加的机器上, 旧的系统就有能力继续处理业务。
sharding 的架构:
ShardRegistry
ShardRegistry是 一个管理集群shard的类, 它主要有如下的功能:
- shardMap: 通过shardID, replicaName, host找到Shard;
- shard与其他的host的网络连接;
- 根据configsvr的shard 集合内容更新shard内容;
- 执行分片的command;
CollectionMetadata
该类记录了集合的metadata, 尤其是集合的迁移相关的信息。
CatalogManager、CatalogCache
CatalogManager及其子类主要是用来enable sharding集合, 以及添加、删除shard等操作, 与副本集的catalog类相似, 主要是用来管理cluster的相关操作;
CatalogCache用来缓存集合的metadata, 主要是对只读的集合metadata。 对于sharding的集合, 很多操作都需要metadata, 通过Cache, 可以方便程序的metadata读取。
Balancer
balancer是一个后台进程的类, 它负责将cluster里面各个shard的chunks的个数的均匀分布, 它通过ChunkManager, 收集到各个shard的chunk 信息, 当2个shard的chunk数差异超过一定的门槛, 就会触发MoveChunk 命令, 进行chunk的迁移。
ChunkManager
ChunkManager用来记录shard的chunk信息, 以及查询的时候, 将查询命令装换成shard key的索引信息;
ShardingState
这个类是DB layer非常重要的一各, 负责记录任务执行过程中, 集群的状态。比如, moveChunk迁移过程中, MigrationSourceManager调用源端接口, 记录需要迁移的chunks, MigrationDestinationManager表示在目的shard转入数据, 以及相应的迁入过程;另外, splitChunk, mergeChunk以及moveChunk过程, 都会涉及chunk的改变, 需要更改metadata以及chunk的分布信息等等。
ChunkMoveOperationState
该类记录了move chunk过程中, runtime的状态, 并且进行持久化;它记录了从源shard 到目的shard, 以及相应的connectionString。
OperationContext* const _txn = nullptr;
const NamespaceString _nss;
// The source and recipient shard ids
std::string _fromShard;
std::string _toShard;
// Resolved shard connection strings for the above shards
ConnectionString _fromShardCS;
ConnectionString _toShardCS;
// ChunkVersion for the collection sent along with the command
ChunkVersion _collectionVersion;
// chunk的最大最小key
BSONObj _minKey;
BSONObj _maxKey;
// 分布式锁, 保护同样的集合进行别的迁移任务
boost::optional<StatusWith<ForwardingCatalogManager::ScopedDistLock>> _distLockStatus;
// _collMetadata记录了该集合的metadata, 以及迁移的时候_shardVersion
ChunkVersion _shardVersion;
std::shared_ptr<CollectionMetadata> _collMetadata;
// 记录了该集合是不是处于迁移过程中
bool _isRunning = false;
DistLockManager
分布式锁的接口类, 通常和CatalogManager搭配使用, 为了获得某个资源, 比如config库里某个集合的修改, 需要分布式锁, 阻止其他节点获得相应的修改权限。
类之间的关系如下图: