Ohhnews

分类导航

$ cd ..
foojay原文

MongoDB中的分片是什么以及何时使用它?

#mongodb#分片#水平扩展#数据库架构#大数据

目录

水平扩展的实用介绍

构建应用程序时,大多数开发者从 单个数据库服务器 开始。

一开始,一切运行完美。

你的应用可能只有:

  • 几千个用户
  • 可控的流量
  • 轻松存放在一台机器上的数据集

但随着应用的增长,一些有趣的事情开始发生。

查询变慢。

写操作变慢。

数据库服务器开始触及 CPU、内存或存储限制

这时,许多工程师会问一个重要的问:

我们是应该升级服务器,还是以不同的方式扩展数据库?

这就是 水平扩展分片 发挥作用的地方。

如果你正在使用 MongoDB,分片正是让你的数据库突破单机限制的机制。

在本文中,我们将介绍:

  • 分片到底是什么
  • 为什么水平扩展很重要
  • MongoDB 如何实现分片
  • 何时应该(以及不应该)使用它

大多数数据库面临的扩展问题

想象一下,你的应用将用户数据存储在一个数据库中。

最初,架构是这样的:

应用
  数据库服务器

所有读写操作都流向一台机器。

这种方法称为 垂直扩展 —— 你不断升级同一台服务器,增加:

  • 更多 CPU
  • 更多内存
  • 更快的存储

虽然这种方法在一段时间内有效,但垂直扩展最终会遇到限制:

  • 硬件升级成本高昂
  • 服务器大小总有上限
  • 升级期间可能需要停机

最终,单台服务器会成为 瓶颈

与其让一台机器变得更大,更好的方法是 增加更多机器

这种方法称为 水平扩展

什么是水平扩展?

水平扩展是指 将数据分布到多台服务器上,而不是依赖单台服务器

不再将所有数据存放在一台机器上:

服务器 A
    2 TB 数据

而是将数据分布开来:

服务器 A → 500 GB
服务器 B → 500 GB
服务器 C → 500 GB
服务器 D → 500 GB

每台服务器只存储 数据集的一部分

这正是 分片 所做的事情。


MongoDB 中的分片是什么?

分片是将 大型数据集拆分到多个数据库服务器 的过程。

每台服务器存储 一部分数据,称为一个 分片

例如,假设一个应用存储了数百万用户。

与其将所有用户放在一台服务器上:

分片数据
分片 1ID 1~100 万 的用户
分片 2ID 100 万~200 万 的用户
分片 3ID 200 万~300 万 的用户

每个分片只包含 该集合的一个子集

当查询到来时,MongoDB 会判断哪个分片包含相关数据。

这使得数据库能够高效处理 海量数据集和高流量

MongoDB 分片集群架构

一个分片集群由三个主要组件组成:分片、配置服务器和 MongoDB 路由器。

1. 分片

分片是 实际数据存储 的地方。 每个分片通常部署为一个 副本集,以确保高可用性和容错性。

2. 配置服务器

配置服务器存储关于集群的元数据。 它们维护的信息包括:

  • 哪个分片包含哪些数据
  • 数据如何分布
  • 分片键范围

没有配置服务器,集群将不知道数据存放在哪里。

3. Mongos路由器

应用程序不直接连接到分片。 相反,它们连接到 mongos,它充当 查询路由器。 其职责包括:

  • 接收应用查询
  • 判断哪个分片包含数据
  • 将查询转发到正确的分片

一个简化的架构如下:

     应用
        Mongos
       /   |   \
 分片1  分片2  分片3

这种抽象意味着应用程序 不需要知道数据存储在哪里

选择分片键

分片键 决定了数据如何在分片之间分布。

例如:

{ userId: 1 }

MongoDB 使用分片键来决定 某个文档属于哪个分片

选择分片键是分片架构中 最关键的决策之一

一个好的分片键应该:

  • 均匀分布数据
  • 避免热点
  • 支持常见查询模式

例如,如果大多数查询基于 userId,将其作为分片键是合理的。

但选择像 country 这样的字段可能会造成 分片不均衡,如果大多数用户来自同一个地区。

创建分片集合

让我们看一个简单的例子。

首先,为数据库启用分片。

$ node
sh.enableSharding("companyDB")

接下来,分片一个集合。

$ node
sh.shardCollection(
  "companyDB.employees",
  { employeeId: 1 }
)

MongoDB 现在已经自动将文档分布到各个分片。

在分片集群中查询数据

MongoDB 中,分片的一个好处是应用程序查询保持不变。

例如:

$ node
db.employees.find(
  { department: "Engineering" },
  { name: 1, managerName: 1, departmentName: 1 }
)

mongos 路由器 会判断哪个分片包含相关文档,并将查询路由到该分片。从应用程序的角度来看,它仍然感觉像是一个 数据库

何时应该使用分片?

分片很强大,但应该只在需要时引入。

以下是分片适用的常见场景。

大型数据集

如果你的数据集增长到 数百 GB 或 TB 级别,单台服务器可能不够用。 例如:

  • 分析平台
  • 日志存储系统
  • IoT 平台

高写入吞吐量

产生大量写操作的应用程序可以从分片中受益,因为写操作可以分布到多个节点。 例如:

  • 事件跟踪系统
  • 游戏平台
  • 社交媒体动态

快速数据增长

如果你预计数据集会快速增长,尽早考虑分片设计可以避免后期重大的架构变更。

何时分片可能过度设计

尽管有诸多好处,分片增加了操作复杂性。

如果你有以下情况,可能 不需要分片

  • 数据集相对较小
  • 工作负载适中
  • 垂直扩展仍然有效

许多应用程序通过 复制和适当的索引 就能完美运行。

通常,应该在 其他扩展策略用尽之后 再考虑分片。

分片 vs 复制

开发者有时会混淆这两个概念。

特性复制分片
目的高可用性水平扩展
数据每个节点相同数据数据拆分到各节点
读取可扩展读操作扩展读写操作
存储数据重复数据分布

在实践中,MongoDB 通常 同时使用两者

每个分片通常配置为 副本集,从而同时保证可扩展性和容错性。

最后思考

分片是 MongoDB 中最强大的扩展机制之一。

它让数据库能够处理:

  • 海量数据集
  • 高查询吞吐量
  • 持续增长的应用

然而,像大多数架构决策一样,应该 谨慎且有目的地 引入它。

理解数据访问模式并选择正确的分片键,对于成功部署分片至关重要。

如果你正在构建预期要扩展到 数百万用户或 TB 级数据 的应用程序,分片将成为数据库架构中的关键工具。

该文章 MongoDB 分片是什么以及何时应该使用它? 首次发表在 foojay