爱吱声

标题: MongoDB架构概览 [打印本页]

作者: shengnan007    时间: 2012-9-18 12:31
标题: MongoDB架构概览
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。
# u( m8 P: `1 [: C6 z. P
: u- @( M, X! o& G. O$ ?$ o, E0 i    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?
5 j3 _3 {1 X1 Q2 f# w0 Z, L, M$ x1 N( e: r, n
    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。
3 c  z2 ~3 Q5 q  b' x/ \9 C. ]( Y1 w' ]; C2 t& q
& U6 x% `1 s5 F9 g
. i" B$ J$ o$ V" \
图1-1 MongoDB架构图
0 [5 o. Y! h  ~; k/ X

. `. n) v% o9 ]    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。
  t: a+ Q2 b+ B  t" j( a' x7 e  \8 ?& V
Shards8 R, E+ |! b$ c; _& A4 T  [

6 f( [3 f7 P  n/ ~    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。) ~' ?. c; h  G; G% q  v

1 {) M& m, K$ {6 a    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。
3 ?& l4 s- j0 Y- t2 \$ |' V) E! b1 h, O2 X) f
    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。. {# L/ h: T- R9 B8 T
9 n9 _) P+ _  P+ S5 _
    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
8 n5 I6 d# D+ S3 |2 p/ V7 ?  s/ V% R) C0 X7 B, g7 h7 F5 o9 F
Shard keys
: j$ `. s( J3 r/ M7 J; j" y        
! e4 T6 C( W5 z" P    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。; _  q" n! g$ Q  H1 }- J4 {
5 [+ n4 _* F" `
    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,
" L3 h2 ~% c$ D6 q: o0 j. v8 M( P7 I6 D  w. s3 P) n% U
{) w" S% ^5 t% c+ F9 G- Y
  "ISBN": "987-30-3652-5130-82",
' j! S7 K% h% [1 L  "Type": "CD",
; |9 J$ @0 u% r/ j. v  "Author": "Nirvana",0 ~" i( q7 i3 `9 R7 U  {; r
  "Title": "Nevermind",3 z* _& D) [' u  O
  "Genre": "Grunge",
" g3 m5 I. R' t( c   "Releasedate": "1991.09.24",
7 C  p& X5 i8 _: v( u. l& H' H, Q   "Tracklist": [. q# V5 p. Q8 l3 G
     {. w) e" X8 b+ G1 l
        "Track" : "1",
) a& G- R* G- Y9 H        "Title" : "Smells like teen spirit",8 `* D4 ]/ ?( a, O) \7 S
        "Length" : "5:02"
4 ^+ s4 }7 C! P8 h9 x     },' Q0 M8 k/ V- @9 C
     {  h/ _. w( L" J: r; h% F: O# H
        "Track" : "2",! C7 t& R5 o( Y1 I- r( K
        "Title" : "In Bloom",
" i$ ]# F) Z2 Z) T  D3 g6 N        "Length" : "4:15"
, _# |: D2 N7 |" v     }, O5 n  ^% K# d  \
   ]% f7 G/ K6 R; S; c8 T& s! @
}
9 ~& h  [# D+ z5 }7 N# V& f4 g/ y7 T! b, T, |8 X4 h$ \" F
{
0 J% w% {' |/ M3 G- H* E  "ISBN": "987-1-4302-3051-9",
" M) f8 A5 w8 c+ W  "Type": "Book",# M* h" }$ ]7 S. T; a
  "Title": "Definite Guide to MongoDB: The NoSQL Database",! H0 F+ j6 O' p0 Z$ d& w
  "Publisher": "Apress",
% W4 C; j7 }* r  "Author": " Eelco Plugge",: q7 c2 K0 L6 k- H% s1 D5 ?6 ]1 L
  "Releasedate": "2011.06.09"0 `- i7 O! a% X) \8 U" {% E! E
}9 Z& O# ~' _( v% w. S" l

. L+ D( f8 c* m* R$ l# n    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。9 ]% I. h( q4 l, Q) H9 [
# l& r' n# x8 `. m4 m
    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。+ f3 r9 y2 D2 V: V  Z

9 \0 ?3 H/ s; f" P  y9 O8 [    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。" k* [- @9 u2 F- X! ]
5 C5 W6 Q) \# O3 R+ g/ d' G
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。; o$ A7 l  T) Q( n; ?  b

3 {2 D: A3 a- L- C3 W$ Y    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。- L9 j4 W2 v4 z  A

5 y+ d: F" z# Z2 ^2 zChunks
7 }  J& f5 u/ R9 N( y) k  f5 x        ; F, O' d4 T) ?% Z
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。6 M9 w' ], U8 m0 I2 `, T: @

# Q* ?6 S+ n; }# W; S

3 z+ j0 |8 W  O图1-2 chunk的三元组
  w, ?; j9 ]  C( E
; t& s! N/ b) U4 D
    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。
! `  _1 G" z$ q. m4 \* d3 L5 A. W8 d3 y. D' e7 ?0 V7 b; O
    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。
6 m9 K/ u' g! D3 o$ |* {
! m: w3 d( P( y    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。, H; D0 ~  u- K  \6 e

; f* S; z& S: j$ N) a) J6 `4 P2 s    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。
8 s  h$ F; F) ?+ \
# Y8 Y8 U8 B  {  j# F    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。
- }( S# r4 {3 M' B- B% }% ]/ r! k; F5 B0 d2 {) H( k2 ~
    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。+ R/ V3 _& E5 L1 G/ L

. n5 \0 o0 K$ c4 O+ l' ?6 }4 LReplica set
7 X6 _& R) L! l6 m5 K* \        
$ `9 z5 Q# G: I/ I6 l    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
" j  m5 T/ y' r( ~
3 \6 m+ i6 T; ]) M9 Y    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。
) h8 c& T  |& s7 w
$ |0 x) r7 D, G/ p3 Q' `; z! L    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。( |) V+ Z: @5 z) q( V0 D' Z

* a( h6 _( G0 @    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。
& ]. z+ r% O$ C) n2 q+ J  Z, \; d2 D* @- g
Config Server7 b/ ?' g! C) R# |9 {& z. k8 S( U
        3 o5 P  n/ c' l) N8 A7 L. c8 x, i
    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。' \, i1 l: U0 Y- u8 q
1 N) N' p: R- X( g/ J5 F
    每一个config server都包括了MongoDB中所有chunk的信息。/ p+ O/ R" e7 A' w' H; ]
, h) G0 J9 v8 ^, t- _( P
    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。" U! {; D! R) ~) l
" e5 u) M, W" j( w* F' a
    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。
$ v: ^- z+ f8 C
( ]2 z# r* ]& r& j; ^, [    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。
9 r; q+ x* I2 e+ [! K
4 g4 x" e) t% J7 b& b4 E" N! AMongos
- r" v* r  \2 q1 z. q, K/ `7 E5 @. c& k# G3 m6 a
    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。5 e9 Q  v. w3 N: F5 M! S
2 U' F; p& L% W# i' a0 M6 c
    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。
) B$ M8 N# w7 n* t  @4 r% n# a) F' W3 H
    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。- F  k( r) ~  o1 w# i

* i) U1 Q  F. h4 X$ B" [    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。" w+ ^, s  D# h0 p# i* ]
5 Y( a9 y' t& @$ M0 I2 O; t7 c
    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。" ~+ E  Q7 D% t

5 @* e# Z* c) @! o6 _
2 ?8 v) `5 {9 Y9 v& BReference,
, M  J1 I9 F0 y$ a$ C+ Q' l# G4 H; D
[0] Architectural Overview
9 ?5 l% U# m% qhttp://www.mongodb.org/display/DOCS/Sharding+Introduction
) X2 K5 @; v4 w9 t! U
作者: PenPen    时间: 2012-9-18 12:40
本帖最后由 PenPen 于 2012-9-18 12:44 编辑
: d) m5 P/ h; v% [0 Z. S) [
& ^, y( @$ J. k! H3 p" b8 n, u, o, O
您是和邓侃一起写文章的盛楠么?
作者: shengnan007    时间: 2012-9-18 12:44
呃。。。是我啊。。。
作者: shengnan007    时间: 2012-9-18 12:44
PenPen 发表于 2012-9-18 12:40 : ]! u+ Y" D6 y' w+ U5 J
您是和邓侃一起写文章的盛楠么?

5 k, u# y: @/ }6 R9 h是我啊。。。这都能被认出来。。。
作者: PenPen    时间: 2012-9-18 12:47
shengnan007 发表于 2012-9-18 12:44
8 x8 Q4 D+ j( c2 m5 s是我啊。。。这都能被认出来。。。
. o; M# J9 U; ^  O: T$ e
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
作者: shengnan007    时间: 2012-9-18 12:49
PenPen 发表于 2012-9-18 12:47
8 \& f- u/ Q6 r" u/ k- n1 r# F这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
; t; n  p- ~4 y' y
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会员是么?
作者: 不爱吱声    时间: 2012-9-18 12:51
shengnan007 发表于 2012-9-17 22:49
. v$ V$ E$ |/ ~. j多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...

- q: N2 t- g& K" P9 H2 I欢迎,欢迎,已经给你变成正式会员了。
作者: shengnan007    时间: 2012-9-18 12:57
不爱吱声 发表于 2012-9-18 12:51 + _& h* K" u2 l3 u" D
欢迎,欢迎,已经给你变成正式会员了。
2 X0 ^. i% _& n0 n7 N, N! ^/ M
多谢多谢啦~~
作者: 巴山    时间: 2012-9-19 03:38
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
3 L, ~9 K3 Z0 d/ H& |) H7 V. ^1 l- {$ `$ H) g" A0 y0 V5 S

作者: 梦晓半生    时间: 2012-9-19 04:21
谢谢。/ {& h- M0 G" u* u; @
# w3 v" k4 L4 r) u" q$ v' I; R
中文看得真累,大部分还是英文术语。$ \4 q7 H* H# m; {, J. f$ }

6 X4 r, I. o4 I0 D) y. K8 b% v' R这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。! s. V+ ?; L$ C" b, o! Q

8 S4 p- l2 K# Q  d现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。
作者: shengnan007    时间: 2012-9-19 08:40
巴山 发表于 2012-9-19 03:38 * \# z9 l* U6 m' c0 v
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
/ m9 m8 i1 A6 D/ m, K& D. k$ j: i$ l' X( C
...
3 |( |; b; l- j; w0 c$ }
mongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的
作者: shengnan007    时间: 2012-9-19 08:44
梦晓半生 发表于 2012-9-19 04:21 ! K4 l3 Z  o; `2 o- ]
谢谢。7 S# e$ t* V+ G1 b# i+ J

: ~% L  l% K# p- H8 c中文看得真累,大部分还是英文术语。

8 z' `" S) {! w7 Q5 y' B% j9 Q现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体系。这个系列文章的目的,是让大家了解mongoDB的基本的运行机理,这样以后使用的时候,可以知其所以然。但是由于这方面的资料很少,我也是到处找资料,写了这么几篇,再往后,就是边使用,边看源码,边写了。
作者: profer    时间: 2012-9-19 14:16
shengnan007 发表于 2012-9-18 12:44 7 S7 ?3 P: {0 m* _3 n: c) c- {- R
是我啊。。。这都能被认出来。。。

+ d. h$ V6 |, W/ x' [是邓嫂么?
作者: shengnan007    时间: 2012-9-19 14:17
profer 发表于 2012-9-19 14:16
, u/ f8 {7 E6 H& G$ \是邓嫂么?

  I' c" X' A5 `是邓的小兵
作者: 恶魔吹笛来    时间: 2012-9-19 18:35
有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
作者: 梦晓半生    时间: 2012-9-20 00:57
shengnan007 发表于 2012-9-19 08:44
, g' v9 |- l- C( @0 u% n2 S现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...

8 Y4 S- l! ?" A) \; W太好了,期待中,希望都带上英文reference。
9 Y! x- t6 M$ x4 `
" U  q1 l9 q2 g5 B! P现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。
! u- a" X) c" a  E8 @/ P/ i% u0 E$ x
http://en.wikipedia.org/wiki/NoSQL
作者: shengnan007    时间: 2012-9-20 08:53
梦晓半生 发表于 2012-9-20 00:57 & _# b' w! G  P% i5 I! v
太好了,期待中,希望都带上英文reference。; e3 N! |8 b+ U1 Z, s

) q" V( u2 i$ ^现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...

( ^1 z2 T8 y( ]现在写的也很纠结,资料太少了,哈哈
作者: 梦晓半生    时间: 2012-9-21 11:52
shengnan007 发表于 2012-9-20 08:53 " e& g' S8 {% Z- w
现在写的也很纠结,资料太少了,哈哈
9 y7 Q* Z2 ^& _! t8 M; M5 D
建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。& S% K$ x5 ?! j& b6 y7 Y
0 p7 Y+ J8 j7 s# K2 ~' B  `
http://en.wikipedia.org/wiki/NoSQL& r0 ?. ]; o$ C6 W3 |

2 K; J9 p: c7 \* E
作者: 定风波    时间: 2012-9-21 17:03
恶魔吹笛来 发表于 2012-9-19 18:35 . I6 P1 q. s+ p' c
有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
+ I: [4 W0 V+ j
有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。
作者: shengnan007    时间: 2012-9-24 09:11
梦晓半生 发表于 2012-9-21 11:52 ' |3 m( a8 s* h/ X! R4 V
建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。9 q, B. s! x' s' P" `5 o

4 }; k: l" G! H! s9 H. zhttp://en.wikipedia.org/wiki/NoSQL
& S+ n; B3 |( B% A9 e/ T6 I
好的好的,现在这个写完,然后开始写nosql




欢迎光临 爱吱声 (http://www.aswetalk.net/bbs/) Powered by Discuz! X3.2