MongoDB

MongoDB 中的数据模型与 MySQL 很类似,MongoDB 中最基本的元素是 Document 即 MySQL 中的数据行。一组结构相近的 Document 可以组成一个 Collection,类似于 MySQL 中的表。多个 Collection 组成一个 DataBase,DataBase 位于一个确定的 MongoDB 集群中。

MongoDB 支持的索引类型非常丰富,包括单字段/多字段/多Key/GEO/文本/Hash 索引,并且拥有丰富的属性:

  • Unique(唯一索引)
  • Sparse(稀疏索引) 只包含索引字段存在的文档,跳过索引键不存在的文档
  • Partial(部分索引) 只包含满足指定条件的文档
  • TTL(超时索引) 当索引上的 TTL 到期后,会自动删除对应的文档

以下对比了 MongoDB 与 MySQL 的各种特性:

MongoDB MySQL
Schema 数据模式上 MongoDB 拥有更好的扩展性,
可以处理多样化和复杂的数据结构
具有固定的数据模式
性能 单点查询速度更快 范围查询更快
事务 只支持单文档 完全支持
JOIN 操作 不支持 支持
查询方式 纯 JSON 操作 SQL
分布式 原生支持 需要手动配置和实现分片

架构

MongoDB 是一个分布式数据存储系统,能自动对数据进行分片,提高集群的吞吐量。在 MongoDB 的集群中包含 ShardQuery RouterConfig Server 三种组件。一个 Collection 的数据会被自动分片,存储到不同的 Shard 上,通常每个 Shard 都是多副本部署的。

Config Server 存储集群的元数据与配置信息,通常也作为多副本部署。这些元信息反应当前集群中数据的分布情况,比如每个 Shard 上存储的分片列表。同时还会存储一些认证信息、分布式锁,为集群提供基于角色的 ACL 控制。

Query Router 为分片服务和客户端提供接口,作为查询请求的路由。 Router 会缓存 Config Server 的元信息,当集群中的元信息变更后, Router 会重新拉取。

分片

在 MongoDB 中 Shard Key 作为分片的唯一标准,可以支持单字段索引和多字段索引(联合索引)。MongoDB 会把 Shard Key 划分成多个相互不重叠的范围,每一个范围都关联一个 Chunk, MongoDB 会均匀的把 Chunk 分配到集群各个 Shard 中。

对于分片 Collection 来说,只有以下的三种索引能作为唯一索引:

  • Shard Key 上的索引
  • Shard Key 作为前缀的联合索引
  • _id 默认是唯一索引,但当 _id 不作为 Shard Key 的前缀时,只能保证每个 Shard 内部的唯一

MongoDB 支持 Hash 分片和范围分片两种方式,其中范围分片更有利于相似数据的存储,加快范围查询;对 Hash 分片来说, Shard Key 的基数对各个分片数据的均衡性有很大影响,如果基数太小,可能导致个别分片数据量过大。

MongoDB 支持根据 Shard Key 划分 Zone,每个 Zone 可以关联一个或多个 shard,同时一个 shard 也可以被关联到任意多个 Zone 上。当集群进行 balance 时, Zone 中的 chunk 只会在当前 Zone 关联的 Shard 中进行迁移。 Zone 适用于以下场景:

  • 隔离 Collection 的中一部分数据
  • 确保数据存储在距离服务器最近的 Shard 上
  • 根据分片的物理性能划分数据

Chunk

MongoDB 通过 Shard Key 将数据分片存储到 Chunk 中,每个 Chunk 的大小/文档个数有一定的上限,当达到上限后就会进行分裂。一个 Chunk 可能会分裂成多个 Chunk,插入或更新都可能触发分裂。分裂不会将数据迁移到其他 Shard 上,但可能造成 Chunk 在 Shard 中分布不均匀,因此 balancer 会进行 Chunk 迁移。

alt

balancer 运行在 Config Server 的主节点上,作为后台进程监视着各个 Shard,负责 Chunk 的迁移工作。其中 A 是 Chunk 迁出的 Shard, B 是 Chunk 迁入的 Shard。

  1. balancer 发送 moveChunk 命令到 A
  2. A 开始内部的迁移操作,在这期间所有对 Chunk 的操作都由 A 负责响应
  3. B 构建所有 A 需要的索引
  4. B 从 A 获取 Chunk 的所有数据副本
  5. 当数据同步复制后,B 开启同步进程,以确保在迁移期间 Chunk 上所有变更都能同步到 B
  6. 当完全同步后, A 通知 Config Server 修改元信息
  7. 元信息更新完成并且 A 上的 Chunk 没有在使用中,则 A 删除 Chunk

alt

参考