Mongo 可扩展性

开启 MongoDB 学习新篇章

Posted by lichao modified on November 8, 2021

可伸缩性(可扩展性) 是一种对软件系统计算处理能力的设计指标,高可伸缩性代表一种弹性,在系统扩展成长过程中,软件能够保证旺盛的生命力,通过很少的改动甚至只是硬件设备的添置,就能实现整个系统处理能力的线性增长,实现高吞吐量和低延迟高性能。

分片(sharding)是指将数据拆分,将其分散存储在不同的机器上的过程。将数据分散到不同的机器上,不需要功能强大的大型计算机就可以存储更多的数据,处理更大的负载。

MongoDB 支持自动分片(autosharding),可以使数据库架构对应用程序不可见,也可以简化系统管理。对应用程序而言,好像始终在使用一个单机的 MongoDB 服务器一样。另一方面,MongoDB 自动处理数据在分片上的分布,也更容易添加和删除分片。

分片集群

MongoDB 的分片机制允许创建一个包含许多台机器(分片)的集群,将数据子集分散在集群中,每个分片维护着一个数据集合的子集。与单机服务器和副本集相比,使用集群架构可以使应用程序具有更大的数据处理能力。

MongoDB 的分片集群由下面的几个组件组成:

  • 分片(shard): 每个分片包含了分片数据的一个子集,每个分片可以作为一个副本集部署。
  • mongos: mongos 扮演者查询路由的角色,提供着客户端应用和分片集群的接口。
  • config servers: 配置服务存储着集群的元数据和配置设置,MongoDB 3.4 以后,配置服务必须部署成副本集。

搭建测试

下图描述了分片集群中,各个组件的交互: 分片集群

分布式架构

MongoDB的一大优势是支持分布式部署,从而提供高可用、高可扩展等特性。因此接下来将会介绍一下MongoDB的分布式部署的架构。

Replica Set 副本集

副本集(Replica Set)简单来说就是一份数据会在多个实例上保存,即保存了数据的多个副本,节点之间通过主从模式进行数据同步,从而可以实现读写分离。同时,副本集还支持故障自动恢复,即节点之间相互有心跳,在主节点挂掉时可以进行重新选举,从而实现高可用。

BSON MongoDB副本集的架构是由一个主节点(Primary)、一个或多个从节点(Secondary)、0个或1个仲裁节点(Arbiter)组成:

  • 主节点负责接收写入请求,并且会对从节点进行数据同步
  • 从节点从主节点同步数据,如果主节点挂掉会参与选举。读请求是否由从节点处理是根据客户端配置决定的
  • 仲裁节点不存储数据,只负责选举时投票

节点之间会定时(2s)互相发送心跳,如果从节点在10秒内没有收到主节点的响应就会判断主节点下线。

数据同步机制

主节点和从节点之间使用oplog进行数据同步,类似于MySQL中的binlog。oplog会记录数据变更的信息,从节点持续从 Primary 拉取新的 oplog 并在本地进行回放以达到同步的目的。oplog是幂等的,多次回放产生的结果相同。

选举机制

选举用于确定副本集的Primary节点,当副本集初始化,或者主节点挂掉时,会触发选举;选举使用raft算法,当某个节点获得超过半数的投票时,可以成为主节点,因此副本集部署时一般会使用奇数个节点。

选举成功之后,选举出来的主节点会有一个追赶(Catchup)操作,即会先检查其它节点是否有比自己更新的oplog,如果没有就直接即位,如果有就先把数据同步过来再即位。

分片集群架构

分片就是为了进行水平扩展,从而使得数据库能够支撑海量数据存储。MongoDB的分片类似于Redis的集群(cluster)概念,将所有的数据按照一定的规则分散在多个shard上进行存储,每个shard只管理自己的一部分数据。整体架构如下: BSON

  • 代理层 mongos:根据分片规则,决定client的读/写请求需要路由到哪一个shard进行处理
  • 配置中心 config servers:负责存储集群的各种元数据和配置,如分片地址。也是以副本集的方式部署的
  • 数据层 Shard:用于存储数据,每个shard也是以副本集的方式部署的。

在一个shard内部,MongoDB还会把数据分为chunks,每个chunk代表这个shard server内部一部分数据;如果单个chunk过大,则会将其进行切分。

因此,数据的增长会让一个shard中的chunk数量变得越来越多,可能会导致各个shard之间chunk数量的不平衡。当shard之间最大和最小的chunk数量差值超过一定阈值时,MongoDB就会启动balancer,进行数据均衡,将chunk从数量多的shard移动到数据少的shard上。

分片方式

用户可以指定使用集合的某个字段作为shard key(分片键),使用这个字段作为分片的依据。分片键必须有索引。根据分片键进行分片的策略主要有两种:

  • 哈希分片:优点在于各个shard的数据分布基本均匀 BSON
  • 范围分片:优点在于可以对分片键进行范围查找,缺点在于如果shard key有明显递增(或者递减)趋势,则新插入的文档多会分布到同一个chunk,无法扩展写的能力 BSON

参考文献

【1】可伸缩性/可扩展性(Scalable/scalability)

【2】MongoDB之分片集群(Sharding)