前言
上一篇介绍了 mongo 的三种部署方式,「单点、主从、副本集」三种部署方式,今天就跟大家聊聊最后一种「分片集群」的方式,分片集群也是 mongo 能够作为万亿级别数据库的核心魅力所在,也有一句话说到:
「连分片集群都不知道,你还好意思说自己用过 mongo ?」
分片集群架构
其他的不多说,我们先甩一张分片集群的架构图
在分片集群当中,一共有以下三种角色
- mongos:路由层,主要用来处理客户端的请求,连接客户端与 shard
- config server:主要用来存储分片集群的元数据和配置信息
- shard:每个 Shard 就相当于一个 mongod 数据库实例,用于存储数据,整个数据库会「分散在不同的 shard 当中」,每一个分片都满足高可用,一般都是一主二从(建议部署位副本集架构),分片的个数最大可以到1024个
一个集群包含了多个分片组成,而一个分片又存储了多个块(每个块包含一定范围片键的数据,互不相交且并集为全部数据),一个块当中包含了多个文档。
那么问题来了-
mongoDB 是怎么做数据分片的?
mongo 提供了「三种方式来做数据分片」
哈希分片
这是很多技术最常用的一种方式,就是将数据通过 hash 散列化,打在不同的机器上,实现「均匀分布」,但是它很大的问题就是「数据不连续」,比如业务需要查询工资在 10000~20000 之间的人员,你可能就需要遍历每一个分片了
范围分片
这种策略直接根据片键的范围确定分片。
比如现在我们将数据在逻辑上分为四个块。
在数据上数据 工资 0~5000一个块,5000~10000 一个块,10000~15000 一个块,15000~20000 一个块,20000~25000 一个块,25000 以上一个块,由于公司人员薪资分布大概率都在 5000~15000,这个区域内,就会造成数据过分集中在 5000~10000 、10000~15000 这两个块儿中,造成「数据分布不均匀」,但是再做「范围查询的时候效率就会很高」
zone 分片
简单来说 Zone 实际上像是范围分片的另一个版本,你为一定范围内的片键制定一个 Zone,然后再将一些分片加入到这个Zone中,于是这一范围内的数据最终就将存储在这个 Zone 中的分片上。
Chunk(块) 分裂
随着数据慢慢的写入,数据量越来越大,当 Chunk 增长到指定大小(默认为 64MB)时,MongoDB 会 对 Chunk 进行分裂。
Chunk 分裂的⽅式
- ⼿动触发
- ⾃动触发:当发生插⼊和更新操作才会触发⾃动块分裂。
JumboChunk 是一个最小的 Chunk 可以「只包含一个唯一的 ShardKey」,这样的 Chunk 不可以再进行分裂。
那么如果数据分片不均 mongoDB 是怎么做的?
这个时候就要说到我们的 「balancer(平衡器)」 了,用来「保证集合的 Chunk 在各个 Shard 上是均衡的」。
当某些分片数据不均匀的情况下,balancer 会发出一个命令让切割器去需要移动的分片上去做数据切割,再把数据移动到数据少的分片上。具体的步骤如下:
- 平衡器向源分片发送 moveChunk 的命令
- 源分片收到命令后,会启动自己内部的一个 moveChunk 命令,如果在数据移动过程中有客户端发来读写请求的话,都会发送到源分片。
- 目标片开始向源分片请求将要移动的数据块的文档,准备拷贝文档数据。
- 当目标分片接收到据块的最后一个文档后,目标分片会启动一个同步进程来检查,是否已经拷贝完全部的文档。
- 当同步完成后,目标分片会连接配置服务器,更新元数据列表中数据块的地址。
- 当目标分片完成元数据更新后,源分片就会删除原来的数据块.如果有新的数据块需要移动的话,可以继续进行移动。
- 配置服务器会通知 monogs 进程更新自己的映射表。
迁移过程对于应用是透明的,但由于「迁移过程会占用相应节点的 CPU 和带宽资源」,因此对分片集有一定程度的性能影响,并且对运维操作存在一些限制。
在对集合进行分片后是否可以更改片键?
「不可以」
MongoDB 中没有对集合分片后更改片键的自动支持。如果在集合分片后必须更改片键,可以按如下方式操作:
- 将MongoDB中的所有数据转储为外部格式,比如可以先放在 mysql 中。
- 删除原始分片集合。
- 使用新的的片键配置分片。
- 预分割片键范围以确保初始均匀分布。
- 将转储的数据恢复到 MongoDB 中。
mongos 是如何处理连接的?
每个 mongos 实例都「维护一个与分片集群成员的连接池」。客户端「一次请求就会占用一个连接」,客户端请求完成后,连接释放。但是客户端数量减少时,这些池不会收缩。这可能导致未使用的mongos占用大量打开的连接。如果 mongos 不再使用,则可以安全地重新启动进程以关闭现有连接。
总结
今天的内容只讲了分片集群相关的,当你看完了以上内容时,再来看看以下几个问题,「mongoDB 分片集群架构是怎么样的?有哪三种分片方式?块分裂是什么?为什么会有块分裂?分片之间的负载均衡是怎么做的?如何修改分片键?mongos 如何管理与分片之间的连接?」
你都会了吗?