爱吱声

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

作者: shengnan007    时间: 2012-9-18 12:31
标题: MongoDB架构概览
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。
7 {$ R! ^1 g8 V. T, ~0 x5 \- e; ~
    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?/ u; V/ V; n; ?2 v7 z1 @/ A

* a) {6 M- |- S- `5 _7 A/ b% O2 F    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。; t2 }' T; s/ O: W
& }8 [" E9 D- _6 t0 @

% a( P  P* @% `. m2 ^/ g/ s& T' Y, o+ b
图1-1 MongoDB架构图

9 Y6 r5 L4 b& Q. U4 }: F$ K7 r. h" F3 g# ?: Z( q
    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。
6 n3 v" |' Z. S7 P/ i
3 f: n$ D$ ]4 I7 C7 j. l, {( }- OShards
9 H5 o+ h9 u, Q$ }
4 N3 d$ i3 K9 i% ?! f    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。7 s: `, ^7 ^* k6 C: Q& S
0 R  k/ `5 J9 J# v9 _
    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。. e6 B8 N' Y2 F7 p: k
, E, V! B1 [2 B
    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。2 ]; t) W0 H( u: D6 R
. k, h4 l+ n- d6 N* |4 E$ I
    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。+ ~- D( `& f8 e* p/ D+ F5 d/ i

& W+ w7 Q3 l5 U. Y- w  N) v1 JShard keys0 m7 ~( ~5 J7 R' l7 ?
        
* w/ j. ~( v# S: B    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。
: ~0 L5 z$ f0 ~+ ?/ ~. |3 ?7 N$ D) a
* `' F. L0 a( z# `8 q4 R' h( N    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,3 D; c) r* q. y9 {( ?+ s4 p

- U* w+ m3 a* V4 e{
; \/ N8 {1 v# k+ b/ m# k  "ISBN": "987-30-3652-5130-82",
# \0 q8 H! ]7 i# U  "Type": "CD",
4 V0 H7 b( R* t# i' _) m5 A  "Author": "Nirvana",) d  E. r/ }3 {: X
  "Title": "Nevermind",- b; x0 a5 e; d
  "Genre": "Grunge",
- Y/ g2 ~2 t8 U8 B# ^   "Releasedate": "1991.09.24",7 f; P2 A" [/ f. Z
   "Tracklist": [
+ W: Q' E- O  N* o1 b* M1 ]     {
( ]5 P8 f; }( c9 p- B        "Track" : "1",. o% {+ o: g% C+ q
        "Title" : "Smells like teen spirit",/ a3 Y: W; L' C7 I% s( {
        "Length" : "5:02"3 [6 Z8 ^- u! h9 q
     },
0 |% d8 V* {) L; A' l1 s& L4 m+ v     {8 T! {7 V/ `6 f
        "Track" : "2",
6 c2 d4 X+ z, D: _        "Title" : "In Bloom",
' G( O" R1 {8 }- s# }: ~# f+ X        "Length" : "4:15"6 h6 y" }  \- {. O
     }* [# }! |2 \$ T2 L2 U% ?+ F
   ]
  _  r! j4 l% n  Q  h5 f9 v' A) ~}2 h& r7 ]- o% a6 \

' D; k- R% ^- a% Y{$ ^0 f% G" L0 ]; K8 P
  "ISBN": "987-1-4302-3051-9",; d2 r7 J! W& S) B9 y7 F( K6 z
  "Type": "Book",
2 o+ ~1 m; r  P  "Title": "Definite Guide to MongoDB: The NoSQL Database",  |5 b5 a0 }/ H
  "Publisher": "Apress",
: b/ L2 P6 ^& H  v' `  L+ ?  "Author": " Eelco Plugge",
) l, h* Z% e% d  "Releasedate": "2011.06.09"& q( {5 M5 g" l3 x
}
5 k7 [+ {4 O( p' U& V9 v4 S+ }
+ [" b" w8 D; J  Q" S    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。
  _2 g/ r5 Y$ u: w+ t2 P( f) ~7 D! y8 k- Z. X
    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。
% K4 m* K- y* K& k' |6 T( G% T& L) d9 o
    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。0 l( P; m9 Q) d% G) }% @
$ v1 G# B- ~9 H9 Z* n' |+ ~
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。
2 m. `" w+ i& u) l8 O. s, z8 n8 i  a& \" E5 M* a+ D" a
    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。
% [/ q. W0 [: c: f  r# }/ H
4 k$ x9 p$ |  T! Q+ qChunks) `2 v: V9 N/ i- H9 ]
        ( w% ^; x$ G4 |4 i- C$ o7 Z2 p
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。; F/ k& C7 x) d; }) i3 P7 x1 f* f

% s# Y! I. E, X/ F
! s$ U) {! `3 _7 v/ s" F
图1-2 chunk的三元组

- m. R, J! f; g; y' b7 D5 \% {  {- p  @+ x2 O/ X* L
    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。
4 W- D. ?# r7 T2 {! s) ]0 \2 H6 @
, H5 q) B! i& w    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。  e  K" O! W( g+ Z* d0 k2 y
' r5 d" w8 U  E
    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。- }( a0 X  Z) q$ p, O" j# J+ S* A
1 `$ x+ N6 G3 M+ U( H# s  e
    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。
1 V9 E& B% H) X- A, B1 d: s+ b. D& O' {( @* a
    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。
3 P/ i) R! f) I+ F6 D- G& T  c# f* m( V* s- Y- q/ O0 q2 V4 r3 V
    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。
$ ~/ W! i4 {) N- p( j5 D
: T  b7 [# a+ SReplica set
- x, X4 H- [' f6 D; {) q6 E        ' I8 k% A3 a9 ?0 n5 D
    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。* \$ r: ]+ X) e! d6 e+ L4 y
1 X( z' X2 p( B5 W8 Y! N2 p. h
    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。
7 g5 T4 \8 p5 |; K. I
) W) {$ F4 w- ~    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。+ k; y3 I* W0 H' U
% H) X& ~$ S) D3 S( F* j
    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。
9 @  @4 t. ?8 V* Q, y
1 @6 U) Q4 E& {; y8 I2 ?; B9 vConfig Server. s) c% d: L! a) s5 }/ Z
        
! Q. B/ R! B- R+ x    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。: l( T- M& f# E

% j: p/ O+ N) T, K    每一个config server都包括了MongoDB中所有chunk的信息。* G% N1 s3 F8 _( c! h& z
1 R5 w4 S; t  e$ M& ]) ?
    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。5 b6 Y1 ~" X+ R6 i
6 ?  A  D8 L& d( g) s
    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。; f' ?7 D5 u0 |. h3 `# C
" U3 ?% E7 I/ k0 `* C
    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。2 n- e6 L0 `% l2 t* [

$ M" k& a6 f1 v, L* E1 D$ J# {Mongos
  ^1 h! h: A2 ]# j
8 J; |( i5 i, ~+ k    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。* u. T7 a8 q# E9 X; A
, F7 H- S7 ~1 a2 ~0 \% E
    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。
# `6 L8 w' U4 S8 O0 Y2 y* F5 v+ ~3 x# {4 V2 _4 D  U
    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。* Q( {5 t3 I; ]
3 @5 ^' G0 j; x
    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。
% K) w6 S% x2 }' J8 ^! ]8 B' N0 j
, [" U2 G4 E" W- ~$ X% j    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。" }9 x2 b: T' \. g7 B9 u2 m
/ {  M3 Z0 f* S7 B& Q5 o# [4 f

+ e- U: O7 {; e; }) v$ VReference,
* P, l7 O3 a! g7 E
9 t( P2 @" Y7 q" l  A5 p  J[0] Architectural Overview0 j5 Z' [9 D8 w+ ?$ L2 k% m5 ]' o
http://www.mongodb.org/display/DOCS/Sharding+Introduction3 `- I) X" D# C0 r8 A: r

作者: PenPen    时间: 2012-9-18 12:40
本帖最后由 PenPen 于 2012-9-18 12:44 编辑
5 \8 l+ v; ^& a% ]: K4 |1 ?
. Z! T9 h8 [5 C1 b9 q. j
& ~0 s) M2 c, F6 L  e您是和邓侃一起写文章的盛楠么?
作者: shengnan007    时间: 2012-9-18 12:44
呃。。。是我啊。。。
作者: shengnan007    时间: 2012-9-18 12:44
PenPen 发表于 2012-9-18 12:40 % l, }3 M* x1 w2 p/ ?5 F3 n- a
您是和邓侃一起写文章的盛楠么?
" z+ p6 G5 b3 I1 Q4 b& \
是我啊。。。这都能被认出来。。。
作者: PenPen    时间: 2012-9-18 12:47
shengnan007 发表于 2012-9-18 12:44 , X: w8 F$ ~' k6 Z6 V
是我啊。。。这都能被认出来。。。
! A- O# T+ Q5 P/ ~* M& k
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
作者: shengnan007    时间: 2012-9-18 12:49
PenPen 发表于 2012-9-18 12:47 7 T4 X; O9 C$ {/ B* p
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
/ i0 h* X- \2 T
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会员是么?
作者: 不爱吱声    时间: 2012-9-18 12:51
shengnan007 发表于 2012-9-17 22:49
! j6 @( q0 z0 r& ~多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...

% R* J8 k( O) S' W! p* ?( F欢迎,欢迎,已经给你变成正式会员了。
作者: shengnan007    时间: 2012-9-18 12:57
不爱吱声 发表于 2012-9-18 12:51   _9 j+ f, s, K% v+ J9 B, T6 g7 z
欢迎,欢迎,已经给你变成正式会员了。

8 z" x- M0 `& q8 ?+ k! G; z多谢多谢啦~~
作者: 巴山    时间: 2012-9-19 03:38
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。7 |5 L! k; u& z& \& w1 R: Y
4 h7 D; @- l' B! W

作者: 梦晓半生    时间: 2012-9-19 04:21
谢谢。$ U) {1 }. r; P4 N3 E$ U- t% T1 ]

1 H5 @* p5 N8 P$ X* g中文看得真累,大部分还是英文术语。
8 N* C' g  a( k$ S( A4 ~& B+ F3 I! A* `7 K! q
这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。
! V$ u8 r4 e+ z# a
$ O( F; ]- m- V% A0 }现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。
作者: shengnan007    时间: 2012-9-19 08:40
巴山 发表于 2012-9-19 03:38 . l9 k9 X5 j$ P" X
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。  J  b! c6 K  t/ r$ {5 N2 l( g. \" G

- k( k3 h; k- M4 h) l ...

9 K4 u" U2 O% B  n0 WmongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的
作者: shengnan007    时间: 2012-9-19 08:44
梦晓半生 发表于 2012-9-19 04:21 4 w; x% a% N2 B) `6 d! v. q
谢谢。
. E9 h# t% f# e
; r8 U8 k$ B' F; x* _中文看得真累,大部分还是英文术语。

! E2 f. N4 v. {3 ]现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体系。这个系列文章的目的,是让大家了解mongoDB的基本的运行机理,这样以后使用的时候,可以知其所以然。但是由于这方面的资料很少,我也是到处找资料,写了这么几篇,再往后,就是边使用,边看源码,边写了。
作者: profer    时间: 2012-9-19 14:16
shengnan007 发表于 2012-9-18 12:44
0 {; y4 l! O6 z& \是我啊。。。这都能被认出来。。。

. L8 X) v( f* Z4 w8 \  i是邓嫂么?
作者: shengnan007    时间: 2012-9-19 14:17
profer 发表于 2012-9-19 14:16
) d- d$ Z% }/ S1 f* ]3 m! T$ v2 M是邓嫂么?
% q6 Q# w. V7 I  O/ I: r6 o( V
是邓的小兵
作者: 恶魔吹笛来    时间: 2012-9-19 18:35
有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
作者: 梦晓半生    时间: 2012-9-20 00:57
shengnan007 发表于 2012-9-19 08:44 1 l8 i- z- L+ w5 K4 n7 V
现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...

' K6 Y+ h- G" R! p+ u: R( J# u  H太好了,期待中,希望都带上英文reference。6 v' n2 y8 o# a4 _5 O# j+ a

  P  n+ H7 O  Y; S; V现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。
5 {" j! Q% ?! Y. @7 `" B) W# h6 C  R4 B- c  f4 [4 {
http://en.wikipedia.org/wiki/NoSQL
作者: shengnan007    时间: 2012-9-20 08:53
梦晓半生 发表于 2012-9-20 00:57 % ]' z5 V2 `# b5 K( {0 t% G
太好了,期待中,希望都带上英文reference。
/ b5 d. q0 B- x" W4 W. ~) r( N. P, n
2 c: o; ?) w  g现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...
$ x8 `' H+ i8 i
现在写的也很纠结,资料太少了,哈哈
作者: 梦晓半生    时间: 2012-9-21 11:52
shengnan007 发表于 2012-9-20 08:53 & ?5 t! L0 I0 H% @  c( V
现在写的也很纠结,资料太少了,哈哈
; D' l) \# J" `% i+ h. M) n
建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
1 H* i6 N- r: x2 {* v2 g. \# M5 u6 V; t# d
http://en.wikipedia.org/wiki/NoSQL7 g; Z5 u, N6 d8 v$ p! [

/ H$ B) J: A; w, B6 Y
作者: 定风波    时间: 2012-9-21 17:03
恶魔吹笛来 发表于 2012-9-19 18:35 . t# o( E& \* A1 P7 S2 ?- R9 \
有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
# _; L7 ~( j3 P+ D1 L7 K$ w' g
有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。
作者: shengnan007    时间: 2012-9-24 09:11
梦晓半生 发表于 2012-9-21 11:52 * R8 t# ~+ Y; _+ A* P
建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
" T  w% N6 |" H6 d* ^, c* T: ^: _% [+ }% j
http://en.wikipedia.org/wiki/NoSQL
/ i& w% q5 \* L9 \) l( ^( A
好的好的,现在这个写完,然后开始写nosql




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