爱吱声

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

作者: shengnan007    时间: 2012-9-18 12:31
标题: MongoDB架构概览
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。
# U5 a$ X3 E; a' X+ }
" o% H- ]3 ?( ]+ @6 s! m3 ~    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?
' p6 |0 t3 n8 _9 a# @5 e6 A
; _2 c5 D& q" d    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。0 L9 g: Q8 F3 f% h  @* M2 f, I

+ R9 r, a2 p' b, K# t. ~. d. ^
$ {) n( e7 k" Y0 G) \
6 Q7 O/ A) V* [
图1-1 MongoDB架构图
- `4 r8 _8 |0 k1 W8 l1 k

$ X0 Z5 B8 }" F    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。
4 G$ g' I; H6 t" w1 O+ @6 g
2 o0 f. }8 {$ Z8 C& hShards
/ i# w2 H+ s- n" \: h9 M) N' f" m' W: b! ?4 f; J
    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。* I% q, y+ {# t, j

/ w( [3 L) }. L- y; B    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。
' i" T0 H: I8 p% Z$ @
/ Y" J4 h) }! ~0 m) w3 D    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。
& x! a. D" P0 }' }' L) V# W; v1 A6 s3 Y7 \+ ^
    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
1 b9 ~, `2 ^! {. P4 f7 T& \7 e
' F! K& o5 Y) `( zShard keys8 ]8 D- Z9 R7 A7 @& P
        ! N% [3 a# R8 f$ A, L. Y& r, k+ c
    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。& v: j- A9 c6 S  o" Y

" c5 ?3 u' R: [0 u; O1 H    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,
5 |0 }1 g( }' J" o+ ]0 G5 H  l
) S) a$ C4 f  i& X. U{( M' R$ f0 A. {. m# b, n
  "ISBN": "987-30-3652-5130-82",
+ _, u( N9 P4 h# ~0 H5 \; ?  "Type": "CD",
5 I+ ~( i* D' n4 U( ^  "Author": "Nirvana",
3 C; X. c0 @2 X! @8 M9 _" U  "Title": "Nevermind",- S3 }7 r% `# R
  "Genre": "Grunge",4 D% _4 Y. |5 C: ?) k+ w/ v
   "Releasedate": "1991.09.24",: o+ C9 {$ [1 g% h, i
   "Tracklist": [
7 m: z3 ]5 }/ ^0 l# M     {
% W- k- C) O5 }6 [0 K8 z- U7 C! v        "Track" : "1",
- Q, M4 H1 O/ F1 @0 N% Q1 [: s) N% s        "Title" : "Smells like teen spirit",
3 }* Q+ ]6 u. g7 m  T' c$ ?" [        "Length" : "5:02"$ G8 B, T5 v9 M1 X
     },
% |( S% _, r7 c+ {( t3 u; b     {
/ w4 U' Z# t/ s/ t2 l        "Track" : "2",
8 b+ d/ o9 N5 a8 A& E0 ~' g9 X        "Title" : "In Bloom",( \) s( K. W) l5 Q5 L8 |
        "Length" : "4:15"
/ {) h  c5 ~5 |8 z1 h     }
3 [4 |2 O9 R0 O7 a- G   ]9 M3 n/ o  l# L
}
' o# B: c4 T$ r" s: e, y) Q& W5 ]
* R( p8 F" l. l3 |{
4 A! P- W2 H2 a6 L, Q  "ISBN": "987-1-4302-3051-9",. b6 T, k) Y5 s( k& a9 p
  "Type": "Book",
1 c* f, L$ c2 u+ }  "Title": "Definite Guide to MongoDB: The NoSQL Database",: k4 {6 b' d3 ]- ?/ l! U6 R6 {3 p
  "Publisher": "Apress",
- k6 R. H( n! j0 u  "Author": " Eelco Plugge",
) Q, c9 [& T; n* R  "Releasedate": "2011.06.09"! l, a( ?" p2 s! n% p+ I5 Z' O$ K8 j
}" f: D8 O" Q- Y+ T
/ w7 L/ [/ M4 d* |5 O1 `' W8 V
    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。
" k! G& S8 b, `0 X5 C* d: N( m: u  K4 j) o
    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。& ]- `$ a6 e" H

0 H4 e" L! z2 {3 w' ]    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。
/ P1 w7 H* {5 ^7 M0 w! i
3 H4 {! [0 Y# d8 z    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。: M4 B4 C! M$ |5 s; w0 O3 J- I# s

0 F! w" A) l! k9 y' O    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。
& E& s. e# Q4 M+ U! B& }5 s( o( C$ a' [/ A6 G1 R' Z; g  ^
Chunks
  _( l6 ]/ Q$ C# n& ?        # [' V. J) |, F" [* }
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。
, l- m. g0 K, i( N1 `
/ A4 _0 [) G& q/ k) o

# _  W3 b# s' c4 F8 }7 M& ^图1-2 chunk的三元组

0 f5 ~0 e: E6 g: C  W3 B- X" H9 w9 F/ I
    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。
3 f; D" X+ D# h" l- n  ^* @7 }! n9 |8 {- e
    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。
$ `% H( d9 |* k" o$ g. u& W$ h( }2 _- ~! N- [. ~$ k0 [
    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。
8 u9 N- d1 O: |. I% s9 ^: }: M, r0 ~
    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。" h; g9 Y/ C, E& ^! W- u8 S$ b

/ x- w7 N0 G' }$ l' u% D9 m    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。
" T- d* |9 q$ c1 r* G* I% o3 G9 i2 Q- a
    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。( E8 I& j) }4 M0 H# m
' ~; H  U0 E& B, f) a- v
Replica set
" V/ o; L0 e1 K0 h; Q6 i        
$ @0 l1 X" ]; w: S6 c& z    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。9 u1 w: c2 x5 G, u3 s4 U7 I% ]

0 j' g3 S) _+ `( E+ P+ \4 e% w    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。/ \) L6 F3 e7 g/ X
1 y! s: {1 h8 _& X1 }' t/ D
    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。$ z+ R" u- C& o, C2 t
( ]7 Q, O. X* F! L. u: F& x& y( @
    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。
1 |5 R: K( p) A; x" q/ I$ m" R& V) {; v/ g) O
Config Server
9 t2 Y, e+ {8 l        
8 h- a: e9 s, T  f& f: c, w0 ~    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。7 D4 R3 M0 a. Q" R& P. I

# h( d! R: g: e" ^    每一个config server都包括了MongoDB中所有chunk的信息。( |! r, D4 P% [( s# S4 H
4 G' y1 |5 A: @: E3 R: Q& n3 j3 \% R
    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。5 c8 j- v! o8 A2 U% z9 @

8 ]! Y; {& q+ U! d5 q    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。: R: F+ K) p7 I0 r2 H( R
1 e- L! z: L) K) w2 Y
    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。
* u8 m" A* U4 |* M
. T5 v' M. E2 C- A: @0 d" FMongos. R1 K% ]: ?7 {6 s* w

' i1 B8 U, @% H! x' S    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。
3 s4 g- q) d9 G0 w3 Y6 v. U  E  P
9 p- g3 L+ Y( C6 r. ?4 t    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。  x5 _5 Z) u- D6 @

4 s' N* F# W- c8 v" u- G  F- [    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。
, d- S; z6 q: J/ m3 y3 m# h4 G
( I) u/ s. J' y. R/ T    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。
- j$ A0 i2 E  C* C# l
- }- L) N$ `7 ?9 G# g    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。
* V7 C* H# Z1 ^$ ^& Y9 F5 v2 `3 `& H% {* o0 s

" g+ r  J* R9 y0 H7 t( x, RReference,
; G: X; z  Z/ K% n: G; Z1 E$ L( }6 p
[0] Architectural Overview
4 [* m* l9 ^7 [0 a. P( N+ D! P' B8 vhttp://www.mongodb.org/display/DOCS/Sharding+Introduction, D+ S9 ]0 i* T+ h( q. W3 Y

作者: PenPen    时间: 2012-9-18 12:40
本帖最后由 PenPen 于 2012-9-18 12:44 编辑 7 A3 \; J( u0 h* o& q
/ z- {& u' Z+ J0 _* k  c. i
. C7 ^; @% I3 L4 Y$ Q+ {
您是和邓侃一起写文章的盛楠么?
作者: shengnan007    时间: 2012-9-18 12:44
呃。。。是我啊。。。
作者: shengnan007    时间: 2012-9-18 12:44
PenPen 发表于 2012-9-18 12:40 7 i' m& A$ K( E8 j6 Q
您是和邓侃一起写文章的盛楠么?

; P. W% Z8 Y; a/ M2 v是我啊。。。这都能被认出来。。。
作者: PenPen    时间: 2012-9-18 12:47
shengnan007 发表于 2012-9-18 12:44
0 W3 J2 p* E, V是我啊。。。这都能被认出来。。。

: J1 X: {# R* d9 Z- E这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
作者: shengnan007    时间: 2012-9-18 12:49
PenPen 发表于 2012-9-18 12:47
0 U5 H* Z$ H8 a, f5 m/ g这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
+ r& I8 K  A- D5 P
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会员是么?
作者: 不爱吱声    时间: 2012-9-18 12:51
shengnan007 发表于 2012-9-17 22:49
, T3 ?! {% W! x' l6 w- \多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...

! S5 ^/ s9 C* s# R7 L欢迎,欢迎,已经给你变成正式会员了。
作者: shengnan007    时间: 2012-9-18 12:57
不爱吱声 发表于 2012-9-18 12:51   S9 f$ o% L0 O% Y. T5 O2 x+ F
欢迎,欢迎,已经给你变成正式会员了。
4 s+ R+ Y/ E4 f. ?' q, r
多谢多谢啦~~
作者: 巴山    时间: 2012-9-19 03:38
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
( J0 C7 N) _2 S- G* K; q# Z: S3 V& `

作者: 梦晓半生    时间: 2012-9-19 04:21
谢谢。
) X! u- x( I. S( f6 S& n
$ F0 I1 H( U3 F8 S中文看得真累,大部分还是英文术语。# g" m' x: G' J
6 v6 c& N5 _' j! v% t
这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。  E% f: S# P* u+ H
# W* s8 K8 A( _/ L
现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。
作者: shengnan007    时间: 2012-9-19 08:40
巴山 发表于 2012-9-19 03:38
. i- _8 t: ?$ b9 b0 M0 u我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
: d, I+ K' J* x7 z
' B2 w& n, W- ]2 F2 B; ^* B) {( t ...
, i2 Q& E+ z# r$ Y% I  W
mongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的
作者: shengnan007    时间: 2012-9-19 08:44
梦晓半生 发表于 2012-9-19 04:21
' Y4 J, X$ ]) _3 u' J  D谢谢。
+ ]+ ]* f) w: ^$ |8 f. t& h* ^+ q5 s  W: E! W
中文看得真累,大部分还是英文术语。

% \- P, y* o% r& [, }( v8 C现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体系。这个系列文章的目的,是让大家了解mongoDB的基本的运行机理,这样以后使用的时候,可以知其所以然。但是由于这方面的资料很少,我也是到处找资料,写了这么几篇,再往后,就是边使用,边看源码,边写了。
作者: profer    时间: 2012-9-19 14:16
shengnan007 发表于 2012-9-18 12:44
1 H* [4 C6 T) [: G# F: t是我啊。。。这都能被认出来。。。
2 T- q9 w0 u1 U+ s: ]! l! X
是邓嫂么?
作者: shengnan007    时间: 2012-9-19 14:17
profer 发表于 2012-9-19 14:16
9 k, g& r* m% M, }% p1 B是邓嫂么?
( `: X8 E, v& e/ F; c0 @
是邓的小兵
作者: 恶魔吹笛来    时间: 2012-9-19 18:35
有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
作者: 梦晓半生    时间: 2012-9-20 00:57
shengnan007 发表于 2012-9-19 08:44
( t* v9 [: c/ e0 }* ^! P现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...
7 u$ H3 l) _6 D. ~' j
太好了,期待中,希望都带上英文reference。
, o& u& z/ o6 c9 a: `; i3 i& C2 c1 w  e/ k0 I0 {- D
现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。
% i" c0 w$ O/ y6 J2 d" D4 I# P4 _* {0 g& u$ k3 Y! R- @* W- v
http://en.wikipedia.org/wiki/NoSQL
作者: shengnan007    时间: 2012-9-20 08:53
梦晓半生 发表于 2012-9-20 00:57 1 S7 F& f' i' Y- y5 k) f
太好了,期待中,希望都带上英文reference。
) A' O& @8 G+ B- Y9 s' T( d0 Y5 ?' L( L, J
现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...

9 K0 g, H' w  U0 ?' e4 Q, A9 v, J* ]现在写的也很纠结,资料太少了,哈哈
作者: 梦晓半生    时间: 2012-9-21 11:52
shengnan007 发表于 2012-9-20 08:53 ( z; o9 Q* ?. \: v
现在写的也很纠结,资料太少了,哈哈

* S) u; [1 X: V" H  s/ E7 s0 p建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
+ }- T/ `  k0 l. \4 O1 X
" n/ t* W% u2 T. qhttp://en.wikipedia.org/wiki/NoSQL
6 k) N* l1 N3 m+ b8 |) A  X+ t, U  q
/ N) J, c9 x, |) x5 g; m
作者: 定风波    时间: 2012-9-21 17:03
恶魔吹笛来 发表于 2012-9-19 18:35
+ |4 k" J2 w3 S% X% i3 Z有点惊讶 居然在这里看到这篇文章 呵呵 静待大作

8 a. S8 P" g+ e! f8 H6 I% V有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。
作者: shengnan007    时间: 2012-9-24 09:11
梦晓半生 发表于 2012-9-21 11:52
* x2 O2 x- K  t0 Z- k建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
# A. u, o! [. X% F  }
6 B4 u1 t" _& q, p* G9 l( A% ]http://en.wikipedia.org/wiki/NoSQL
9 `4 R4 J7 Y% Q' ~& }7 m
好的好的,现在这个写完,然后开始写nosql




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