设为首页收藏本站

爱吱声

 找回密码
 注册
搜索
查看: 4724|回复: 2
打印 上一主题 下一主题

[信息技术] Sharding中Chunks的切分和迁移

[复制链接]

该用户从未签到

跳转到指定楼层
楼主
发表于 2012-9-18 12:37:48 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
    在上一篇文章“MongoDB架构概览”中,我们简单介绍了一下MongoDB中的shard,接下来,我们详细的讲解一下MongoDB的sharding model。5 }, K( U  b0 j5 }

1 I( m' @3 h: w; y    当MongoDB的一个 collection 数据量太大时,我们按照shard key,把该collection分成多个chunks,多个chunks聚集在一起,组成了一个shard。, f9 d! [4 ]( E" P& C

( \9 }& `; [1 T% y7 e    每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。如图2-1所示。( U6 i& p7 I8 R* O5 s$ J

. {0 c0 z/ h% J" [  Q/ g
5 w, Q: W" j  g8 j9 I3 E

! y; F! |9 D  z( B图2-1 shard key、chunk和shard的关系

+ G$ H# d$ [+ Z9 N+ I$ S    通过图2-1我们可以看到,数据在整个key space上的分布是不均匀的,这就导致了chunk中存储的数据量会不均匀。如果一个chunk中存储的数据太多了怎么办?多个chunks构成了一个shard,因此shard中的数据量也会不均匀,如果一个shard中存储的数据太多了怎么办?
- K! q/ c  _! a7 d
6 G5 u; l8 P  i9 @4 v8 y8 e    上一篇文章中,我们提到了解决办法。一个 chunk最多能够存储64MB的数据。当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。
, T2 _$ e1 f( H1 |
! E) \3 E8 [1 Y    当用户产生存储数据的需求时,把插入数据的请求发送给mongos,mongos先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers,同时,mongos会根据历史上插入的每条数据的平均大小,判断这条数据插入到这个shard server的某个chunk后,是否会导致这个chunk的大小近似达到或者超过64M。
- ?1 R/ y: u, R- h& T7 x6 |
4 L& }! Z+ E" d9 G6 v, N    如果mongos经过判断,发现chunk在插入这条数据之后,会近似达到或者超过64M,那么就说明这个chunk需要进行切分。Mongos就要和这个chunk所在的shard server联系,并发送一个切分chunk的请求。4 N4 K  k0 @; {: D& O/ v

* \# P/ _  W6 ~+ T6 f  f! }  l5 d    Shard server接收到mongos发送的请求之后,首先查询这个chunk的shard key range,然后根据这个key range,计算一个midpoint,然后把chunk从midpoint处分为两部分。同时,把这个变化通知到config server。1 G) |9 A! D2 X. B$ G/ X

5 t- |  t. O! h    请注意,这里只是切分chunk,切分后的chunk仍然在这个shard中。随着系统的运行,chunk中的数据量在增长,虽然通过切分操作,保持每个chunk中的数据不超过64M,但是, shard 中包含的 chunk 数量在增长。如果 shard server中的数据太多了怎么办?MongoDB通过chunk的迁移,来均衡shard servers之间的数据量。1 u0 [+ J. I9 L. u1 y. V- l" }0 N6 i

  k2 r  O( V9 ^) p$ j    在mongos上运行着一个“balancer”进程,这个进程的任务是确保每个shard servers上的数据规模大致相同。当数据规模不均衡的状态被检测到之后,这个balancer会联系那个数据较多的shard,发出一个chunk迁移的命令。* i4 B0 P, @7 T7 F5 [0 r
; J( t" {( s- M7 J( s( }/ @! K
    如何界定什么是数据规模不均衡呢?如果存储chunks最多的shard server,比存储chunks最少的shard server,chunks的个数之差超过预定的一个阈值n,balancer就向这个 shard server,发起chunk迁移指令。
+ Z9 H; K3 Z6 x! n- }' @& V" S
# C+ ]0 r1 S  G- B9 x" n. j    在MongoDB中,n的值,与一个collection可以分成多少个chunks有关系,chunks的个数越多,n就越大,但是至少n要大于2。当shard servers中chunks个数的差值小于等于2的时候,迁移就可以结束了。
6 n) F, H$ \+ |! ]4 q: y
. ^( N( m" b7 ^4 x3 z, j    Chunk的迁移是在线进行的,也就是说所有的shard server都处于工作状态。Mongos从数据多的shard server中,选择一个chunk,迁移到一个数据少的shard server中。 为了方便理解,下文中,我们把数据多的shard server叫做orig server,数据少的shard server叫做dest server。( Z" c& z  ^$ K/ V) v* g

5 D, `0 N$ t! X2 y. x! {    迁移的过程中,首先 orig server向 dest server联系,成功建立数据通道之后,chunk数据会被从orig server拷贝到dest server。这个过程会持续一段时间,时间长短,取决于数据的大小,如图2-2中的过程A。; g) u( z% h$ v+ c
& _' X- b; T' V) @, w7 O7 p
    在这期间,orig server可能会不断接收到mongos转发来的用户请求,包括insert、update等等,导致这个chunk包含的数据发生变化。这些新增的数据变更会被记录下来,不妨称之为 delta update。当过程 A 结束后,orig server 将向 dest server传输delta update,如图2-2中的过程B。
7 [, F; z6 |, u$ X  O. f
6 E* q/ r' f7 `1 W8 I7 X/ B* e+ ]    在执行过程 B 期间,orig server很可能继续接收到mongos转发来的用户请求,导致这个chunk包含的数据进一步发生变化。当 orig server向 dest server,传输完第一轮 delta update以后,紧接着开始传第二轮 delta update,然后传第三轮 delta update。如此反复更新 delta,理论上可能会永久地持续下去。' O+ M# ~1 I. q; q3 a8 b
" g; U. z5 a) ?7 A& k8 }7 I7 L3 c
    为杜绝这个可能,我们可以设置一个最大的传输轮次,当进行到最后一轮传输时,orig server会停止接受来自mongos的所有更新请求,并把这些请求记录下来。, L6 o* _3 `3 ^9 y- a
/ g3 {. z/ B) |2 Z7 P% I2 K

' j: {2 V- f6 V3 k0 r2 O
图2-2 chunk的迁移过程
当最后一轮传输结束之后,会经过如下的几个步骤来结束chunk迁移的操作。
1.  Dest server会通知config server,该chunk已经从orig server迁移到了dest server中。Config server更新这个chunk的映射信息,如图2-2中的过程1。
2.  Dest server通知orig server,数据传输已经结束,让orig server向 Mongos,提交一个StaleConfigException,如图2-2中的过程2.1和2.2。
3.  Mongos会从config server查询到 dest server 的地址,如图2-2中的过程3.1。
接着,从orig server获取到最后一轮传输时,orig server尚未执行的,来自用户的数据更新请求,如图2-2中的过程3.2。
最后,Mongos 从orig server 获得这些尚未处理的请求后,把它们转发给dest server处理,如图2-2中的过程3.3。
4.  以上的过程结束之后,在未来的某个时间,orig server会把这份数据物理删除。
在迁移的过程中,存在着一种特殊情况。假如这个被迁移的chunk,正面临着高频率的更新请求,那么在传输delta update的时候,会发现delta update越来越大,以至于delta update的增长速度,大于从orig server到dest server的传输速度。
在这种情况下,整个迁移过程要中断,之前所传输的所有数据都被放弃,也就是图2-2中的过程A和B,以及过程 1-3,通通被放弃,相当于这个迁移操作没有发生过。Mongos会从 orig server 中,选择另外的一个chunk,重新开始迁移操作。选择的标准,是这个chunk 的数据更新的频率不高。

( _. i# z- F6 C& z! u  q
Reference
[0] MongoDb Architecture

评分

参与人数 1爱元 +10 学识 +5 收起 理由
不爱吱声 + 10 + 5 谢谢!有你,爱坛更精彩

查看全部评分

该用户从未签到

沙发
发表于 2012-9-27 17:18:01 | 只看该作者
底层运作机制最迷人。

该用户从未签到

板凳
 楼主| 发表于 2012-9-27 17:53:29 | 只看该作者
puber 发表于 2012-9-27 17:18 / y/ g6 _& j; \9 v+ C1 ?9 u+ M' @- U
底层运作机制最迷人。
* p4 a2 R& b! S+ U7 Y
也最不好寫呀

点评

对技术宅来说,只要能搞懂,一切都是值的,因为那代表终极快感。:)  发表于 2012-9-27 18:02

手机版|小黑屋|Archiver|网站错误报告|爱吱声   

GMT+8, 2026-3-7 10:05 , Processed in 0.071121 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表