爱吱声

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

作者: shengnan007    时间: 2012-9-18 12:31
标题: MongoDB架构概览
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。
9 `* ~" U' R' e% R4 i& ?4 Y  x' |. S9 U' w
    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?" \6 z, `* F5 K- W; d: c2 B
4 I, ^7 l' h# |9 w2 f5 n, {$ G
    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。# v& t3 V5 U/ Y& c

& S; `4 b7 m0 z7 `, X" n
4 S9 b# n: Y. _$ W1 C: P- x3 Q- d
  V' s1 A# }8 O/ O& K2 R: e; v
图1-1 MongoDB架构图
8 x5 }4 T5 T) O; o) Z2 g. I

2 X0 G( v2 k& `2 O- z    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。) h7 [% |- w  \/ b

5 L6 n3 d6 O1 }( D$ `" E- @Shards
- g/ a8 G7 A7 c/ j  g4 l8 Z+ r$ Q. b3 n7 A6 l
    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。
, x' b; B, p% R4 c% z$ R* P# b: P: J( G( d% }3 @
    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。, y2 P* a0 L0 O. M7 r9 J/ L0 V

+ J: w* i$ W: [  V    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。. v+ }. V( K5 M# v/ ?* q; u
; N$ B) {' `, K2 ?9 I! X
    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。; Y, y8 o9 x3 |* v4 z5 [$ C
( a( j8 B& a9 _( F+ s
Shard keys9 E0 Z  L1 m' ]% ~: a4 T
        
- G& J. }9 a2 \0 T: g    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。
" _1 c# R! M& C; i: O3 h$ L- b6 y8 L& p8 h" ]: q, z
    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,
- |- Z# M7 R( A- [9 I. T' V
8 B9 U: g& e8 A. {) d& d* |{
9 q! O5 l# U$ T/ y  "ISBN": "987-30-3652-5130-82",
" d9 l1 E3 t( S' z) \) t  _  "Type": "CD",
  x' p* |# o/ g+ L  "Author": "Nirvana",$ i* R; i/ D& u1 e$ k) r3 N2 I
  "Title": "Nevermind",1 c  |/ p. ?& b9 w1 x
  "Genre": "Grunge",
5 y2 s! x$ i, P8 W, N   "Releasedate": "1991.09.24",: I0 |4 o; k8 s8 h) t* S- X$ S
   "Tracklist": [! ~& q2 h4 A0 A. c# E- o9 i* `
     {$ ^5 I$ b5 z; e- [6 f4 ]: K
        "Track" : "1",& _5 p7 f! E" O$ g
        "Title" : "Smells like teen spirit",
% D$ U( M7 p! l+ ^# s( Z$ F        "Length" : "5:02"1 \- ^" d$ I6 P# C" }. w" |  G! E. e
     },4 V7 }7 L# e; j# K* C
     {
0 ~9 L- ]: g% d: ?, `& m        "Track" : "2",0 p' f5 p" Z" c
        "Title" : "In Bloom",& H4 W/ |9 C) O
        "Length" : "4:15"3 P2 h7 Q! y/ {$ K3 H2 m& g  ?  G' c
     }
" y% k* D) [2 M8 q$ a6 x$ {   ]+ o$ c. [0 F% }+ t! y7 ]( T
}
1 U+ V# \9 K( [  \& m* n- N7 z: C+ r* m4 E- F) F
{$ Y% C2 U; \! C
  "ISBN": "987-1-4302-3051-9",6 C4 u2 G( V) S( r% U/ Q
  "Type": "Book",. y7 a1 Q( o+ w2 J5 b
  "Title": "Definite Guide to MongoDB: The NoSQL Database",0 _9 n1 ~& \' F0 C5 M1 P
  "Publisher": "Apress",2 a4 p* }' z/ ?# c: O
  "Author": " Eelco Plugge",2 ]' ^& Y% a* G! A% Q, b9 [
  "Releasedate": "2011.06.09"
. O# F$ [1 s# b  B8 M}# r' V) Y/ I' y' v  q; o, P, a
" \# I: Q7 Z8 o" ]
    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。# n  @3 m/ c: K% `

8 a2 _2 c0 P' {& T/ C9 ]* S    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。
% r( V* V" p& P! a3 t9 Y+ {$ D! I' q1 k; K5 Y  }3 Y
    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。
' r; Q4 H+ f* T- f
3 u8 W4 Y4 \: q/ h  q    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。
& S! @+ ^% G0 X; J  F
1 u* I1 u6 q' R    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。; x8 L4 |* V( D' F

) U, |" K* N0 n' f% GChunks
. @; p4 m5 S  u* [! F        ! U& v8 ~( A; s% Q( x
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。9 Q% X  X& u( `# I; X/ L

3 F$ v/ s: X* v6 h1 T

5 f, U8 J, @. r" Y图1-2 chunk的三元组

4 |* u* ]- e8 r7 L# r2 F" I* @" L/ D9 ~- E# W
    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。& z2 c& [0 E7 v. O1 v" D8 i

& u4 p! I* E' z7 l' S$ v, }    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。. C+ G4 J' k$ v% p( d( i
. P# Y, s  e- U; q; u7 {7 H
    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。8 M2 s5 m. O5 N0 N5 P  O" P! X
+ w7 y4 C& A! N' D( O
    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。% V' q( `- v% q" U4 W; f
3 \; g. ~/ y8 K# i( r1 u: R
    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。
4 G# w8 Z5 a# u$ u1 m' C& ]
1 ~) {4 z5 U0 l" }    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。! x9 A/ D0 ~6 ?

) c- [# Q  Q" o. ]' @8 _Replica set0 X% n+ M6 @; h( R0 t
        # e( `) Y# y( _3 y5 j/ d
    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
$ J. z, `/ T" `& a; Y
7 l# T  d& S  S+ |6 h2 f9 y    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。
2 T$ e3 ^# N7 C5 r
' U+ }. m- B: I6 e5 D7 l    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。
& W0 \0 j" Q% y& L6 L
5 M$ D7 y1 ]! ?4 c" i    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。
* {0 k& c. }% I
/ n4 ]0 I) A" t$ p' \% W' X, RConfig Server# W- I! E; |8 y8 ^* u# k- N
        3 [  n  |/ W  e6 p0 C
    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。6 j# H' {- i( N! x! I

7 b# G9 s7 h( R( X( P. l5 l  M    每一个config server都包括了MongoDB中所有chunk的信息。
7 M: l  S( l. d
7 J; d$ ?9 H) N    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。8 Y; Z% o& J" R/ I: l% D6 x  L4 s

3 e. m% _0 p. e4 e! Q( o- N    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。: S# @6 W# \/ \) H0 Z
4 m7 c1 Z' B& B3 H$ u
    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。
% j, D6 x" {5 Q* Z, m5 U9 @6 o
( p% A5 b1 {' ^% ^- iMongos
0 W; u9 v" p6 v+ J
: F+ x7 K) Y1 A$ e* J* C0 R* h    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。
6 t$ w; o* A" N  t$ B/ r3 ^! j+ e  k6 |0 ]/ P* X
    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。
  j1 P8 O# H5 u8 [# ]  f3 ]- h: Z
, y" f: u$ y1 O# o! W    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。
  q$ }/ h/ g6 }- G9 |9 W8 h( `) l( Z$ }. x* X
    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。0 u& l- ?. r" w% u& e: _5 m( I

: ]* g2 S/ g) ?7 P+ N/ d+ [  q: V    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。% A7 V. [+ G2 E3 v+ b( q# A

* i- v6 a" I3 Y! B- f
9 q' p; H- X  }  s! ZReference,
" ~/ x* @: g7 m2 E( d% v8 v' q4 K) p7 c: V8 O7 t! A+ u/ K
[0] Architectural Overview; H2 {  q& S& z0 K5 ~0 w  }
http://www.mongodb.org/display/DOCS/Sharding+Introduction
7 |8 }& f/ l5 G& O0 H( R
作者: PenPen    时间: 2012-9-18 12:40
本帖最后由 PenPen 于 2012-9-18 12:44 编辑 ' N" {1 ]* m' Y, @

/ z$ x, i% d. z+ b% K1 v: f3 `/ r4 Z6 b' H: q% {
您是和邓侃一起写文章的盛楠么?
作者: shengnan007    时间: 2012-9-18 12:44
呃。。。是我啊。。。
作者: shengnan007    时间: 2012-9-18 12:44
PenPen 发表于 2012-9-18 12:40
- q2 k! V, f6 T+ Y7 L% g您是和邓侃一起写文章的盛楠么?

8 G+ ^7 Z9 W$ S* o4 F是我啊。。。这都能被认出来。。。
作者: PenPen    时间: 2012-9-18 12:47
shengnan007 发表于 2012-9-18 12:44
2 P9 b2 ~1 G) Q# r4 [/ V是我啊。。。这都能被认出来。。。
6 z8 X: h" H5 M1 Z; Q# L* {
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
作者: shengnan007    时间: 2012-9-18 12:49
PenPen 发表于 2012-9-18 12:47 + H" V1 c- _/ ]3 u7 C
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
4 e) m: _7 D* L; U4 @1 }( i- P
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会员是么?
作者: 不爱吱声    时间: 2012-9-18 12:51
shengnan007 发表于 2012-9-17 22:49 4 |6 c% n! N$ r0 h1 V8 `
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...

* a7 [' j: [2 a: A8 V: V欢迎,欢迎,已经给你变成正式会员了。
作者: shengnan007    时间: 2012-9-18 12:57
不爱吱声 发表于 2012-9-18 12:51 ( L7 I3 f( \  p( I- g9 }1 A% k
欢迎,欢迎,已经给你变成正式会员了。

/ p  e, {5 Z7 e7 h% \! S多谢多谢啦~~
作者: 巴山    时间: 2012-9-19 03:38
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
7 B) d. W# l# h, p3 Q& \7 w0 o( Q: I- |

作者: 梦晓半生    时间: 2012-9-19 04:21
谢谢。
; {; J( G+ f6 [  j$ ^4 }
8 F& O2 l- r1 A6 l' i; U* a9 V中文看得真累,大部分还是英文术语。! Y" U5 S. L/ j; E  O
( B4 ?8 L  s: _! D/ K4 S* j
这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。2 _% h( T; q, H/ Y
# B- A/ s2 s3 q( v8 a
现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。
作者: shengnan007    时间: 2012-9-19 08:40
巴山 发表于 2012-9-19 03:38
& w  J4 j2 {+ y6 D2 v! _我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。  `6 B% q- c1 M
8 L& ?2 b2 X& L& x. N' C
...
7 `" _/ q  f. j) {' A
mongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的
作者: shengnan007    时间: 2012-9-19 08:44
梦晓半生 发表于 2012-9-19 04:21
" s: v! `0 i" H( b6 K! E谢谢。/ E6 S' T! M5 \' p' K
. s& {& Q6 |% G% S5 X6 Y5 B! [
中文看得真累,大部分还是英文术语。

4 S  u/ H4 {6 \0 Q现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体系。这个系列文章的目的,是让大家了解mongoDB的基本的运行机理,这样以后使用的时候,可以知其所以然。但是由于这方面的资料很少,我也是到处找资料,写了这么几篇,再往后,就是边使用,边看源码,边写了。
作者: profer    时间: 2012-9-19 14:16
shengnan007 发表于 2012-9-18 12:44 / \2 Q4 {+ t+ [1 x+ t7 k; g
是我啊。。。这都能被认出来。。。
7 ~6 \, T# Q: i" n
是邓嫂么?
作者: shengnan007    时间: 2012-9-19 14:17
profer 发表于 2012-9-19 14:16 , }, M; M* A% H( D6 G3 I" ]" Y- W
是邓嫂么?
0 ]8 p; ]- _4 r& Q- H9 v. f
是邓的小兵
作者: 恶魔吹笛来    时间: 2012-9-19 18:35
有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
作者: 梦晓半生    时间: 2012-9-20 00:57
shengnan007 发表于 2012-9-19 08:44 6 \$ N4 |+ w- Z( ~
现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...

8 x  `8 ~9 m6 s9 d太好了,期待中,希望都带上英文reference。; A( H9 t- ?8 [  R# Q- D$ o

7 I& I2 W# k9 p* m( U+ w$ m- \现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。
6 ]( ~/ O1 }9 z! U  x: M
* b- `; M# D7 G/ p3 l. chttp://en.wikipedia.org/wiki/NoSQL
作者: shengnan007    时间: 2012-9-20 08:53
梦晓半生 发表于 2012-9-20 00:57
5 B6 U( }/ Q% |1 k太好了,期待中,希望都带上英文reference。7 i2 ~' O! g, P' Q$ `0 X

) ]8 w# S& ~7 j! h4 E- N5 e现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...

" ~4 Z+ X7 L$ f: O现在写的也很纠结,资料太少了,哈哈
作者: 梦晓半生    时间: 2012-9-21 11:52
shengnan007 发表于 2012-9-20 08:53 . h3 p7 ?, s0 ?' q9 Q
现在写的也很纠结,资料太少了,哈哈
( m0 Y' N" Q" l$ N3 [
建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
+ f6 ~+ C1 l) d% {6 e, n/ z: G- U! ^* k
http://en.wikipedia.org/wiki/NoSQL0 c  x  _, V  P; K" L  I* B" W+ w4 y4 t$ L

! _7 R$ U  O7 J2 N# h: z! x/ s" M* O
作者: 定风波    时间: 2012-9-21 17:03
恶魔吹笛来 发表于 2012-9-19 18:35
( l  _& Q8 K! W/ ?- a. v9 ~$ V* O有点惊讶 居然在这里看到这篇文章 呵呵 静待大作

8 Z4 u. j% m# Q% U" e有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。
作者: shengnan007    时间: 2012-9-24 09:11
梦晓半生 发表于 2012-9-21 11:52
! G, G* n% u1 Z1 V建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。, b  V; f5 i8 X8 d2 D
+ b2 C7 L$ c9 |; C) h/ j
http://en.wikipedia.org/wiki/NoSQL
9 w8 ^- J' [9 R0 G
好的好的,现在这个写完,然后开始写nosql




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