MongoDB 分片(Sharding)

        分片是MongoDB用来将海量的数据水平分割到不同服务器(或者说一个集群)上所采用的方法。尽管分片起源于关系型数据库分区,但它完全是另外一回事。MongoDB的最大区别在于它几乎能自动完成所有事情,使用者通过简单的配置就可以很方便地构建一个分布式的MongoDB集群。


理解分片
为了建立、管理或者调试集群,需要了解分片的基本工作模式,接下来我们从如下几个部分了解分片的基本工作模式。

1、分割数据
分片是集群中负责数据某一子集的一台或者多台服务器,举个例子,如果有一个集群存储了1000000份代表网站用户的文档,则一个分片可能包含其中200000位用户的信息。
一个分片可由多台服务器组成,如果分片包含不止一台服务器,则每台服务器都有一份完全相同的数据字节的副本,在生产环境中,一个分片通常是一个副本集(replica set)。









上图中一个分片包含数据的某一个子集,若某一个分片包含多台服务器,则每台服务器拥有一份完整的数据副本。
为了在分片间均匀地分配数据,MongoDB会在不同的分片间移动数据子集,它会根据片键来决定移动哪些数据,比如我们可能选择按用户名(username)字段来划分用户集合,MongoDB使用基于区间的方法进行划分,即按照给定区间将数据分割成不同块,比如["a","f"),注意,在该章节中使用标准的区间符号来描述区间。"["和"]"表示闭区间,而"("和")“表示开区间,因此,有4种可能的区间:
x在(a,b)中,表示当且仅当存在x使得a<x<b。
x在(a,b]中,当且仅当存在x使得a<x<=b。
x在[a,b)中,当且仅当存在x使得a<=x<b。
x在[a,b]中,当且仅当存在x使得a<=x<=b。
MongoDB中分片多用[
a,b)来表示区间范围,所以这会是最常见的形式,该区间可以表述为:从a开始且包含a,到b为止但是不包含b。


2、分配数据
MongoDB划分数据的方法有些不直观,为了理解这么做的理由,我们先使用初级方法,遇到问题时再寻找更好的方法。

一分片一区间
分配数据到分片最简单的方法是让每个分片负责一个区间的数据,所以,如果我们有4个分片,则很可能会得到如下图所示的设置,在这个实例中,我们假设所有的用户名都以a到z之间的字母开头,其范围可以表示区间["a","{"),其中{是ASCII码中字母z后面得字符。



在上面图中这4个分片,区间分别是["a","f")、["f"、"n")、["n"、"t")和["t","{")
这种分片体系非常简单易懂,但是在一个大型或者繁忙的系统中却会带来许多不便,如此分片导致的后果是什么呢?
假设许多用户首字母的范围["a","f")中的名字来注册,这会导致分片1较大,因此我们需要拿出它的一部分文档将其挪到分片2上去,我们可以调整区间使分片1(比如说)变成["a","c"),使分片2变成["c","n"),如下图所示:





上图中分片1迁移部分数据到分片2,分片1的区间缩小而分片2的区间扩大




上图中,一分片一区间会导致级联效应:必须易懂数据到下一台服务器上,即时不能改善平衡性。
如果添加一个新分片又会怎么样呢?假设这个集群继续工作下去,最终每个分片上都有了500G数据,然后我们添加一个新分片进来,现在我们不得不把400G数据从分片4挪到分片5上,将300G从分片3挪到分片4上,将200G从分片2挪到分片3上,将100G从分片1挪到分片2,整整移动了1TB的数据!如下图所示:

上图中描述,添加一台服务器并使集群负载均衡,我们可以通过在集群的中间(分片2和分片3之间)添加服务器来降低所需迁移的数据量,但即时这样仍然需要迁移600G的数据。
随着分片数量和数据量的增长,这种级联效应只会持续恶化下去,因此MongoDB并不采用这种方式来分配数据,而是使每个分片包含多个区间。

一分片多区间
让我们重新回顾上述的一片区一分区的情况,其中分片1和分片2各有500G的数据,而分片3个分片4各有300G数据,这次我们允许每个分片包含多块区间。
我们可以把分片1上的数据划分为两个区间,使其中一个包含400G数据(比如说["a","d"),另外一个包含100G数据["d","f"),接着我们对分片2也做同样的处理,得到区间["f","j")和["j","n"),现在我们可以把100G数据["d","f")从分片1迁移都分片4上,把区间["j","n")内的所有文档从分片2迁移到分片3上,如下图所示:

说明:
一个区间的一个数据称为一个数据块(也叫块,chunk),当我们把一个块得区间一分为二时,一个块也就变成了两个块。
如果添加新分片,MongoDB可以从每个分片顶端取100G数据并把这些块挪到新分片上,使得新分片获取400G数据需要移动的数据量最小化,只有400G。如下图所示:



说明:
上述图中添加分片时,每个分片都可以直接给它提供数据。
这就是MongoDB的数据分配之道,当一个块变得越来越大时,MongoDB会自动将其分割成两个较小的块,如果分片间比例失调,则MongoDB会通过迁移块来确保均衡。








猜你喜欢

转载自blog.csdn.net/dongnan591172113/article/details/58586870