MongoDB 部署模型
在生产环境中,MongoDB 经常会部署成一个三节点的复制集,或者一个分片集群。
我们先来看左边,当 MongoDB 部署为一个复制集时,应用程序通过驱动,直接请求复制集中的主节点,完成读写操作。另外两个从节点会自动和主节点同步,以保持数据的更新。在集群运行的过程中,万一主节点遇到故障,两个从节点会在几秒中的时间内选举出新的主节点,继续支持应用的读写操作。
我们再来看右边,当 MongoDB 被部署为一个分片集群时,应用程序通过驱动,访问路由节点,即 Mongos 节点,Mongos 节点会根据读写操作中的片键值,把读写操作分发给特定的分片执行,然后再把分片的执行结果合并,返回给应用程序。
那集群中的数据是如何分布的呢?
这些元数据记录在 Config Server 中,这也是一个高可用的复制集。每个分片管理集群中整体数据的一部分,也是一个高可用复制集。此外,路由节点(Mongos 节点)在生产环境通常会部署多个,这样整个分片集群就没有任何单点故障。
mongod 是 MongoDB 中的一种进程,是 MongoDB 服务器的核心组件,负责管理 MongoDB 数据库系统中持久化存储、查询处理、数据索引和复制等任务。
mongod 进程运行时会监听 MongoDB 服务器的默认端口(27017)等待客户端的连接请求,当客户端连接 mongoDB 后,就可以通过 mongod 提供的服务进行数据的 CRUD 操作、查询语句和聚合功能等操作。此外,由于 MongoDB 具有水平扩展的能力,所以 mongod 也会负责数据的分片,保证集群中每个节点的数据负载相对均衡,从而提高整个 MongoDB 集群的可扩展性和性能。
MongoDB 与关系数据的对应关系
- 关系型数据通常有数据库和表的概念,对应 MongoDB 里则有数据库和集合关系
- 数据库有主表和子表,对应 MongoDB 里通常使用内嵌的子文档或内嵌数组
- 关系型数据里有 Index 索引,MongoDB 里也有类似的概念
- 关系数据库里一条数据称为一行,MongoDB 里则称为一个文档 Document
- 关系型数据库里的列,对应 MongoDB 里成为一个字段 Field
- 关系数据库里经常使用 Join 连接操作,对应 MongoDB 里通常使用内嵌方式解决,如果使用 Linking 方式,对应使用 $Lookup 操作符,也可支持左外连接
- 关系型数据库里还有视图的概念,对应 MongoDB 里也有只读视图和按需物化视图
- 关系型数据库里会有 ACID 的多记录事务,对应 MongoDB 里则有 ACID 的多文档事务
MongoDB 数据层次结构
MongoDB 里面数据主要分为三层,文档(Documents)、集合(Collections)和数据库(Databases),多个文档存储在一个集合中,多个集合存放在一个数据库里,每个集群里面可能会有多个数据库。
- 数据库(Database): Products
- 集合(Collections): Books,Movies,Music
数据库和集合的组合,构成 MongoDB 的命名空间。
- Products.Books
- Products.Movies
- Products.Music
数据库名最长不能超过 64 个字节,命名空间最长不能超过 120 字节。FCV >= 4.4(指 MongoDB 功能兼容版本在 4.4 或更高版本时),命名空间长度限制为 255 字节。
MongoDB 为什么只有左外连接?
- 反范式设计
- 读取效率低下
- 分布式环境
MongoDB 里面连接 Join 操作只有左外连接,因为 Join 这种操作是违反 MongoDB 设计的初衷的,这种操作经常要对两个表的不同数据进行连接操作,而这些数据在物理存储的时候,通常不是在相邻的区域里面,读取的效率比较低。
此外 MongoDB 是一个分布式的环境,当进行 Join 操作的时候,可能在分片一上要连接的一条数据可能在分片二上,下一条数据可能又是另外一种情况,在这种情况下数据库很难保证整个操作的性能。
基于这些原因,MongoDB 只提供左外连接,并且要求 From 表不能是分片表,左边的表(主表)可以是分片表。
参考资料
- 玩转 MongoDB 从入门到实战