前言
随着互联网和移动网络的发展,用户和数据规模不断增加,传统单机关系型数据库已难以满足需求,尤其是对于文档、图片、报表、视频等非结构化数据。为此,NoSQL数据库应运而生,如基于键值的Redis、基于文档的MongoDB、基于列的Cassandra、基于图的Neo4j等。其中,MongoDB凭借其对半结构化和非结构化数据的优越支持,成为其中的佼佼者。
基本介绍
MongoDB 是一款无模式的分布式文档型数据库,旨在为 Web 应用提供可扩展且高性能的数据存储解决方案,适用于海量数据存储和实时查询。在某些简单场景下,MongoDB 的性能可以高出 MySQL 数倍。
需要注意的是,MongoDB 采用无模式设计,”无模式” 并不意味着完全没有模型设计,而是允许灵活的建模方式,解决了传统数据库在改表时的复杂问题。为了追求更高的性能和水平扩展性,MongoDB放弃了强事务支持和关联查询,也不支持SQL,省去了SQL解析和优化过程。
特性介绍
技术特色
1、基于 JSON 的数据模型:MongoDB 使用 BSON(Binary JSON)作为其存储格式,这是一个基于 JSON 的二进制序列化格式,用于存储文档和远程过程调用。与 JSON 不同,JSON 是无类型的,而 BSON 能够指定数据类型,使得存储的数据更为精确。BSON 的二进制编码序列化格式不仅支持数据类型和长度的编码,还包含一个头部区域,用于存储元素的长度,从而可以更快速地定位和跳到文档中的指定点。因此,相较于 JSON,BSON 在遍历时的速度更快。此外,BSON 还扩展了多种数据类型支持,如二进制数据、日期、UUID、正则表达式和 JavaScript 等,使其能存储更多样化的数据类型,并更好地支持复杂的数据模型。与 JSON 相比,BSON 在数据序列化与反序列化时表现出更高的效率,既提升了数据存储和传输的性能,也增强了在不同应用场景下的灵活性。
2、灵活的动态数据模型:MongoDB 的文档支持多态性,即在同一集合中的不同文档可以拥有不同的字段。这意味着文档中的字段可以是字符串、数字、布尔值、数组、对象等多种数据类型。这种灵活性使得 MongoDB 能够方便地建模各种结构的数据,并根据需求的变化调整数据模型,无需像关系型数据库那样进行复杂且成本高昂的 ALTER TABLE 操作。因此,MongoDB 提供了极大的灵活性,适合在动态和变化频繁的数据模型中使用。
复制协议
MongoDB 的复制协议类似于 Raft 协议,采用复制状态机(Replicated State Machine,RSM)模型。日志的复制和应用顺序是:首先将日志复制到多数节点,然后再应用到状态机。这确保了在领导者(Leader)切换时,新领导者能够保持一致的日志顺序,只有在多数节点成功复制日志后,才会进行应用。
然而,MongoDB 的日志复制和应用顺序有所不同。它先将日志应用到主节点(Primary)的状态机,然后异步地将日志复制到从节点(Secondary)。这种方式可以提高主节点的性能和响应速度,由于复制是异步的,从节点的数据可能会有一定的延迟。
与 Raft 更注重一致性不同,MongoDB 更侧重于性能和响应能力,通过异步复制方式优化主节点性能,追求最终一致性而非强一致性。
分布式ID
MongoDB 是一个基于分布式文件存储的数据库,每条文档记录都有一个 _id 字段作为主键,默认情况下,这个主键使用的是 ObjectId 对象,它是一个 12 字节的 BSON 数据。ObjectId 的结构如下:
前 4 个字节:表示创建时间的时间戳,记录自 UNIX 纪元以来的秒数。
接下来的 3 个字节:机器标识符,用于区分不同的服务器。
紧接的 2 个字节:表示进程 ID。
最后的 3 个字节:递增的计数器,从一个随机值开始递增。
需要注意的是,MongoDB 的 _id 字段是一个自动生成的唯一标识符,通常由客户端生成,这样可以提高随机性,减轻服务器的负担。如果客户端未提供 _id 字段,MongoDB 会自动生成一个 ObjectId 作为主键。生成规则保证了每个 ObjectId 的唯一性。
架构说明
MongoDB支持两种主要的集群架构:副本集(Replica Set)和分片(Sharding)。副本集主要提高系统的高可用性,而分片则是通过分布式架构来提高系统的性能。以下是对这两种架构的详细介绍。
副本集架构
副本集的部署方式能够保证高可用性,主要通过节点间的心跳机制来维持集群的健康状态。每个节点会定期向其他节点发送心跳信号,确保集群能够及时感知到节点的故障或状态变化。一旦某个节点无法接收到主节点的心跳信号,从节点会主动发起选举,选出新的主节点以继续提供服务。
默认情况下,节点会每2秒向其他节点发送心跳。如果备份节点在10秒内没有收到主节点的响应,它会启动选举机制,选举产生一个新的主节点来接管原主节点的工作。这个过程对应用是透明的,由Driver层来自动处理,而分片架构则由mongos路由层感知集群状态的变化。
副本集采用Raft选举协议,在此协议中集群中的大多数节点必须保持可用,以便选举产生新的主节点。如果集群中大部分节点不可用,则集群将降级为只读模式。为了避免选举过程中的冲突,建议副本集的节点数为奇数,通常推荐使用三副本部署。在资源有限的情况下,可以通过添加不存储数据的仲裁节点(Arbiter)来实现。
分片架构
当数据量超出副本集的处理能力时,MongoDB的分片架构提供了一种有效的解决方案。分片架构的主要优势是提高了性能,能够通过分布式系统进行横向扩展。
总结来说,MongoDB副本集提供了高可用性,确保即使某个节点失效,集群仍然能够继续工作;而分片架构则通过分布式技术实现了横向扩展,提升了数据处理的性能。当用户的数据量远超单一副本集的处理能力时,分片架构成为理想的解决方案。
数据拆分
MongoDB的分片架构将数据分布在多个分片节点上,以便处理大量的数据。在分片过程中,MongoDB使用的是“chunk”块机制,每个chunk代表一定范围的数据,MongoDB会根据特定字段的值域将数据划分为不同的chunk。根据分片策略的不同,这些chunk可以分配到不同的Shard(分片节点)上,配置中心负责维护这些映射关系。此外,分片策略的选择(范围拆片与哈希拆片)直接影响数据分布和性能。分片策略本质上就是形成值域的策略而已,MongoDB支持两种拆片方式:范围拆片,哈希拆片。
范围拆片(Range Sharding)
范围拆片的核心思想是根据字段的值范围来划分数据。MongoDB会使用指定字段的值域,将数据划分成多个范围,每个范围对应一个chunk,并将这些范围的chunk分配到不同的分片上。
优点:
排序列举友好:由于数据按顺序分布在不同的Shard上,范围查询时可以直接顺序读取,从而提高查询效率。
缺点:
热点问题:如果Sharding Key的值域存在集中趋势(例如,时间戳字段),则可能导致某些特定值的chunk过于集中在一个Shard上,造成单个Shard负载过重,而其他Shard则处于空闲状态。例如,如果所有数据的时间戳都有相同前缀,那么它们很可能会分布到相同的Shard中,从而形成“热点”,影响系统的负载均衡。
哈希拆片(Hash Sharding)
哈希拆片将Sharding Key值输入哈希函数,计算出一个整数值,之后通过哈希算法将这些整数值分配到不同的Shard上。这种方式的分片更为均衡,因为哈希值的分布是随机的。
优点:
均衡性好:由于哈希算法的随机性,数据会均匀地分布到各个Shard上,从而避免了热点问题,增强了集群的扩展性。
计算速度快:哈希计算的时间复杂度通常较低,因此数据分片时的计算效率较高。
缺点:
排序列举性能差:由于数据分布是随机的,按某个字段(如name)进行排序时,几乎所有的Shard都会参与查询。这意味着范围查询或者排序查询的性能较差,因为数据并不是连续存放在单个Shard中的。
MongoDB的分片机制提供了两种常见的分片策略:范围拆片和哈希拆片。范围拆片适用于有顺序或范围查询需求的场景,但可能引发热点问题;而哈希拆片通过均匀分配数据,解决了热点问题,但可能影响排序和范围查询性能。选择适合的分片策略需根据具体的业务场景和数据访问模式来决定。
片键选取
分布式系统中,片键(Sharding Key)的选择对性能至关重要。一个理想的片键应该具备以下几个特性:
1、均匀分布更新:所有的插入、更新和删除操作都应当在集群中的所有分片上均匀分布。这样可以避免某些分片过载,而其他分片则闲置,确保集群的负载均衡。
2、均衡分布查询:查询操作应该在集群中的各个分片上平均分布,这样能够提高查询效率,避免某些分片成为查询瓶颈。
3、针对相关分片的操作:更新和删除操作应仅发送到存储被修改数据的相关分片。这样可以减少跨分片的操作,提高效率,避免不必要的数据传输。
4、查询只在相关分片上执行:查询应该只在存储相关数据的分片上执行,避免发送查询到不存储查询数据的分片,从而提高查询的响应速度和效率。
选择一个理想的片键,有助于最大化分布式系统的性能,减少不必要的开销,并确保系统在处理大量数据时依然能够保持高效和稳定。
运维指南
应用场景
适用场景:
1、实时数据存储:如网站访问日志、埋点数据、交易流水等。MongoDB 的无模式特性使得它在存储各种格式的数据时非常灵活,减少了开发人员为不同数据格式设计统一结构的工作量。
2、数据缓存:由于其高性能,MongoDB 也非常适合作为缓存层使用,帮助系统在重启后保持持久化缓存,从而避免对底层数据源的过度访问。
3、大规模、低价值数据存储:在存储大尺寸但低价值的数据时,传统的关系型数据库可能显得成本较高,MongoDB 提供了一个较为经济的替代方案。
4、高伸缩性场景:MongoDB 适合于由数十或数百台服务器组成的数据库架构。它已经内建对 MapReduce 引擎的支持,便于在大规模数据处理时进行高效的分布式计算。
5、对象或 JSON 数据存储:MongoDB 的 BSON 格式非常适合存储文档结构化数据,支持灵活的存储和高效查询。
不适用的场景
1、高度事务性应用:如银行或会计等金融系统。对于需要复杂事务和原子操作的场景,传统关系型数据库仍然是更合适的选择。
2、传统商业智能应用:商业智能数据库通常会对查询性能进行高度优化,针对特定分析需求进行调优。在此类场景中,关系型数据库可能会提供更强的查询性能和优化能力。
模式设计
模式设计是为应用程序服务,而不是为了存储优化。为实现最佳性能而设计,必要时需要进行反范式设计。由于MongoDB放弃了MySQL的强事务支持和关联查询,所以在使用过程中,最好将需要的数据冗余存储到一条记录中。
性能优化
读懂慢日志
看懂执行计划
> db.collection.method(...).explain(<mode>)> db.collection.explain(<mode>).method(...)
说明:explain有三种模式:
· queryPlanner:默认值。查询计划的选择器,首先进行查询分析,最终选择一个winningPlan。
· executionStats:执行统计层面,返回winningPlan的统计结果。
· allPlansExecution:返回所有执行计划的统计,包括rejectedPlans。
索引解读
MongoDB索引遵循最左前缀原则,使用单个索引尽量覆盖多个查询。
TTL索引注意
MongoDB 的 TTL 索引允许文档在指定时间后自动过期并被删除。该索引是通过后台单线程定期检查(默认每 60 秒一次)并删除过期文档的。如果写入量较大,导致有大量待删除的过期文档积压,可能会出现过期文档未能及时删除,进而持续占用存储空间。
上一条:docker离线安装
下一条:购软平台是MongoDB代理商
品质保证
多年的生产力软件专家
专业实力
资深技术支持项目实施团队
安全无忧
多位认证安全工程师
多元服务
软件提供方案整合,项目咨询实施
购软平台-找企业级软件,上购软平台。平台提供更齐全的软件产品、更专业的技术服务,同时提供行业资讯、软件使用教程和技巧。购软平台打造企业级数字产品综合应用服务平台。用户体验和数字类产品的专业化服务是我们不断追求的目标。购软平台您身边的企业级数字产品优秀服务商。