爱吱声

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

作者: shengnan007    时间: 2012-9-18 12:31
标题: MongoDB架构概览
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。
# O! J: c9 f3 |: d. w- M; R" s8 q) N; v, Q8 _
    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?
, V. G6 x' b% k2 e/ r! m9 d
* q9 T& C+ L7 l% Z3 x( |! y5 s" T  k    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。
; }- ^6 P0 B, E" ]: T3 J. I" \+ @0 a3 e- }9 p, B& y5 z* G/ ^

& K9 `, h+ R4 |' q: M9 r4 \( {: F) y' b# U  }, k+ r$ z. X# k
图1-1 MongoDB架构图
& g6 u& s$ D" ^: p
2 v0 T. t/ Q+ j
    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。) b( V# ^2 h5 [; i! O1 {2 ~9 L/ V

& W" V6 R# I  b1 z1 x# LShards
1 c( z# ~& D4 N6 \4 M8 i
* H: D$ Y3 i, l( N1 {    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。
% f8 d7 n5 K- _3 Q* V' v9 o4 t4 g4 w+ ^/ k- N
    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。+ D4 W8 P0 a4 D
6 G1 w8 g0 I* }' l1 \( V
    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。* L; H- i* z+ g# f+ n/ \5 ]
7 l( O6 K, \, b- y7 v3 X
    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
" K- Z$ U2 E  B/ V3 _. O9 a
( Y- m& a  l' y/ RShard keys% {0 `% I9 V! Y) N6 {- J! z
        . Z& a1 l; r2 h1 R
    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。
7 j8 A# h# h8 }/ @2 t1 ^- ?& x$ ?9 F% s5 [2 u
    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,; K/ o/ f2 j- D! L+ q+ Z

4 q6 }  l0 f$ A. a9 g( K{
; i. k, m% v  T  "ISBN": "987-30-3652-5130-82",/ D# N" p4 r/ G  R
  "Type": "CD",3 b3 z* p! M: e
  "Author": "Nirvana",
. y/ S* \# A/ e! F7 d( {9 b  "Title": "Nevermind",
7 T- U" b9 ~) L, Q  "Genre": "Grunge",
$ G+ P0 X$ I4 L0 i$ k   "Releasedate": "1991.09.24",/ K0 D" Q& W2 q5 m) O6 g, A1 h
   "Tracklist": [% k0 c$ {0 [9 g/ s) K1 |6 L
     {2 a# j) v# u+ a$ g- {
        "Track" : "1",$ J' d# A; ^# A" t6 b
        "Title" : "Smells like teen spirit",
+ T# p3 Z9 q5 F6 t& ]; b6 p        "Length" : "5:02"
3 b) s- h3 {2 W7 v9 n     },
. i+ _! r+ W, S& d0 q* o     {/ {; m. Y0 a( n' \/ n1 v* o
        "Track" : "2",0 N2 d, b- K$ o4 E6 ^2 b" ]
        "Title" : "In Bloom",
3 s5 [% z: ^) j( w' V' l3 b        "Length" : "4:15"8 }5 @7 O6 P5 L; X* x& ?- q* r
     }
! M3 H9 g$ w' Z9 U- {2 e   ]! W3 H1 h# q1 Y# M$ N
}
0 {; h7 N/ C. _* f6 Z6 q" Z3 i4 Z- V# ?+ b9 X1 p( m
{
1 T# i' L. A* Y  "ISBN": "987-1-4302-3051-9",; ~5 y3 c% E' v- N6 _  w) W
  "Type": "Book",
: j1 y  ], n% |/ o# B+ [" }0 {6 h9 z  "Title": "Definite Guide to MongoDB: The NoSQL Database",
* s4 m" m, c# o& r  "Publisher": "Apress",8 j  |  g% O" }  d. ^
  "Author": " Eelco Plugge",. P# F# h; \' e- i
  "Releasedate": "2011.06.09") @: [* K+ P: ]
}( m- W. {7 {/ O. O" G( p- _! t

& Y" {: J0 w0 ]* ~% e    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。
1 p0 T  n& a7 U% {& D2 V0 H& q$ n# G, h! o$ i
    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。! o8 L: i- J4 {

# P& }5 Q+ k$ G- G9 Z; V    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。# d2 U- f' P% J
2 r1 M) k/ ]" T& m
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。
: Y% X! D  u' j$ e' A9 u+ D+ t# T, D! w1 N& a' L  ]
    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。
9 s2 H7 L; r' W8 J& f+ @0 F# b( r; }$ H0 l' i! [
Chunks
" x6 ^2 C3 _7 Z( c* ?2 r        
# U9 M6 w7 n3 N. I8 ^. M    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。
/ _9 y' i" o7 a1 d2 a, O
/ d" ]4 t' n  \% A" ?+ X6 e+ j
" u5 f6 x. P8 Y
图1-2 chunk的三元组
+ M! ~! H( v* z, s" }9 D

$ c" F0 k' C1 A1 [    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。4 L, s& i$ W$ G& j# B; q7 m
& U/ L( _/ [, E7 G" c& p
    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。1 X7 k* c  `# F% e( ]% f' v

% d4 d( p# j8 |2 G$ i2 R- g    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。: x/ U) m. J4 }  c; ^9 |

$ M3 ~1 H* C7 D( P8 c0 k4 n# \    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。
8 @. L4 w& {& \, f8 q2 ^- S0 b0 a- e
, H, V5 N( L: b/ m    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。) O/ B6 N4 _# l/ O$ u$ v/ o! v7 v

5 ?! W1 @9 q3 Z/ U8 [% O    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。; {7 p& L! H8 N' S/ Y

8 k# k9 ~* m1 E6 ZReplica set
( w) H9 X5 q2 L* }! r        . M& r0 ~0 U4 P. H2 p2 Y# E
    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
# G+ V, }$ l2 x' E
! o$ d0 z  k' }& A( U    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。
; q2 C: N5 j) A' i% w! b: y0 K- i7 w) ^6 D  z
    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。. P3 N; y4 s+ O# B2 J& q
' j2 O* D$ w. H$ k7 T! V& E  G
    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。5 @4 p- z  W( `

8 f$ w, A. l" P7 r  Q3 o! n: Y# ?! gConfig Server  B+ u  i- N; u& B8 C
        - K! X0 W' h7 ~" w1 B8 {
    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。* ~7 U# S+ i1 P# M) j, Q
9 \, s; a/ D7 S
    每一个config server都包括了MongoDB中所有chunk的信息。
# a/ ?+ q9 G# m+ B3 p
* U5 t. k/ K: |9 S4 ^    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。! T8 o4 U5 M3 ?) y$ h
1 |% w. Z1 s+ h6 v/ O7 }( x' s
    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。) r1 a" c+ f$ U( B7 s; w7 \
0 H& \+ A- m1 _* B' t& b: [
    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。8 T9 \) x' X- B, |5 O! z

- }' O: O7 D6 k/ CMongos+ G( ]( O1 t# \2 b' J

/ u5 C6 g+ d" B& w2 y- W- T2 X! v- i: t    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。5 k: x8 R+ _4 S+ u0 r. P) k
/ y  ?) v: J3 Q; l: A8 o  d
    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。
( v9 }" f( u! R# G5 }% d9 b7 ?% S/ s+ O! k1 r7 V$ O* U
    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。8 P( H( h0 G& d) d( |* h

4 `, z9 ~& m3 q4 z* a5 _7 P' y0 j) \2 z    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。7 r, l' g6 i3 J) s
" Q- E) ?9 C3 X2 U
    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。
4 j. r; m( G4 F( J! N6 d; B  Y
. E2 }9 }0 z/ p0 n" t' C% L; y7 f7 E; Q5 U0 b0 i
Reference,
! A" V/ h' X! c4 c2 N, k  V) P+ |  {, I6 o
[0] Architectural Overview6 D7 ]$ `# o( w- U/ B. e
http://www.mongodb.org/display/DOCS/Sharding+Introduction/ |7 f; B" s* S5 k- _" D: n! C

作者: PenPen    时间: 2012-9-18 12:40
本帖最后由 PenPen 于 2012-9-18 12:44 编辑 , O9 O. Q: B5 {5 h! O. b" N# i
; e/ q9 m& ?# q" T4 H
! z  x* ^0 T/ N4 z( d; H
您是和邓侃一起写文章的盛楠么?
作者: shengnan007    时间: 2012-9-18 12:44
呃。。。是我啊。。。
作者: shengnan007    时间: 2012-9-18 12:44
PenPen 发表于 2012-9-18 12:40
, N1 h4 t2 A4 b* T您是和邓侃一起写文章的盛楠么?
( _  I" w- y5 s: ~% {3 B' k
是我啊。。。这都能被认出来。。。
作者: PenPen    时间: 2012-9-18 12:47
shengnan007 发表于 2012-9-18 12:44 ! Z$ a6 {6 X0 n; K6 L$ O+ y( `
是我啊。。。这都能被认出来。。。
( B% v; B9 R' m9 |' x1 D
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
作者: shengnan007    时间: 2012-9-18 12:49
PenPen 发表于 2012-9-18 12:47
8 ~- L+ h' `# X7 [( [# K& @, t4 N这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

  H" }1 d1 _  |多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会员是么?
作者: 不爱吱声    时间: 2012-9-18 12:51
shengnan007 发表于 2012-9-17 22:49
: R( ?, o) a& ?7 k8 P多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...

( g6 X. h7 \' F# k欢迎,欢迎,已经给你变成正式会员了。
作者: shengnan007    时间: 2012-9-18 12:57
不爱吱声 发表于 2012-9-18 12:51 ; ^& u1 W5 I# t0 y' M
欢迎,欢迎,已经给你变成正式会员了。

7 ]/ U7 U0 G; J5 k5 }- |1 _5 M4 F多谢多谢啦~~
作者: 巴山    时间: 2012-9-19 03:38
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
2 n$ r, b" Q8 M5 u' t) R$ k9 T1 Q' r4 ?3 M9 ]* q. ~  _5 D0 S7 n. i

作者: 梦晓半生    时间: 2012-9-19 04:21
谢谢。
0 }# E* I. o8 \( `9 }1 Y4 H! D& m
2 M6 U) U' B2 Q& j( I3 h中文看得真累,大部分还是英文术语。
3 x" r0 R1 u/ O+ H/ a; Z
3 l" n8 J% g; P/ f这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。' t) C& ?1 n0 f# S6 ?+ ?

1 S7 B. X0 z' j4 c/ t现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。
作者: shengnan007    时间: 2012-9-19 08:40
巴山 发表于 2012-9-19 03:38 4 S* y$ k, {1 w" T% B; U! y
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
" v' _9 i* F9 G" j+ W9 H
2 F" ^9 ~& C2 w) b9 ^ ...

5 H, q# Q; ]% kmongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的
作者: shengnan007    时间: 2012-9-19 08:44
梦晓半生 发表于 2012-9-19 04:21
9 C* }: P+ A* M" Q5 z谢谢。$ M3 Q' B* M* C4 r
7 I1 l# e. u* n2 P0 J( x
中文看得真累,大部分还是英文术语。

; B7 L& N- t* x2 Z! v$ ~现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体系。这个系列文章的目的,是让大家了解mongoDB的基本的运行机理,这样以后使用的时候,可以知其所以然。但是由于这方面的资料很少,我也是到处找资料,写了这么几篇,再往后,就是边使用,边看源码,边写了。
作者: profer    时间: 2012-9-19 14:16
shengnan007 发表于 2012-9-18 12:44 ) \, R  ?# z0 f5 Z, |/ @) u
是我啊。。。这都能被认出来。。。
+ E1 N. f, }/ N3 H
是邓嫂么?
作者: shengnan007    时间: 2012-9-19 14:17
profer 发表于 2012-9-19 14:16 ! \. t1 |, n. R4 K6 v
是邓嫂么?
: y; m0 B: d; L2 l
是邓的小兵
作者: 恶魔吹笛来    时间: 2012-9-19 18:35
有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
作者: 梦晓半生    时间: 2012-9-20 00:57
shengnan007 发表于 2012-9-19 08:44 ( |3 {  h, x2 }; Q/ m) ?
现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...
+ i: O9 q8 A8 n0 n/ T. |
太好了,期待中,希望都带上英文reference。
2 `  y( W, b; N6 D" P5 B8 U' z+ C0 A/ Z" Z
现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。$ N. j: c6 f9 {

; f, p! S; @! O$ j* h6 d; `http://en.wikipedia.org/wiki/NoSQL
作者: shengnan007    时间: 2012-9-20 08:53
梦晓半生 发表于 2012-9-20 00:57
( @' J. G* H' t& Y% F太好了,期待中,希望都带上英文reference。  o/ S9 v" B" I

9 A2 |% @2 r. R& z; L, i0 o现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...
2 T  {/ {  ]5 w, m2 l
现在写的也很纠结,资料太少了,哈哈
作者: 梦晓半生    时间: 2012-9-21 11:52
shengnan007 发表于 2012-9-20 08:53 $ q: ~( k0 d# S1 m1 M: ^  `# z' Q
现在写的也很纠结,资料太少了,哈哈

2 J- {, l- _7 B建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。: ^: U' @- H+ f$ u; t; C

- |" H2 X+ c2 J! X6 ehttp://en.wikipedia.org/wiki/NoSQL  I/ B' n% t2 R+ P: F

, Y2 P; w4 z2 L- P* C$ d- S8 K& l2 z
作者: 定风波    时间: 2012-9-21 17:03
恶魔吹笛来 发表于 2012-9-19 18:35 ) R- T4 ^' j1 H
有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
; [9 o+ X, {$ m8 F+ w& Y; ]! Q% _- B
有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。
作者: shengnan007    时间: 2012-9-24 09:11
梦晓半生 发表于 2012-9-21 11:52
0 n) z3 g! V1 i3 `9 t0 I# }建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
' r) |. z3 V1 m- E( y& t. O1 o! i5 ?+ D' n* Q; r5 r
http://en.wikipedia.org/wiki/NoSQL
( e) h0 j. K% a( p, r) L# r
好的好的,现在这个写完,然后开始写nosql




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