爱吱声

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

作者: shengnan007    时间: 2012-9-18 12:31
标题: MongoDB架构概览
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。( r) a( }0 K' u! b8 Q

: W! o7 o1 |; o6 M+ u5 U2 |    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?
( L& I) z, a: H9 j
, K7 L! S% E! x0 J5 i    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。1 Y/ `7 b8 ~  {
# c4 e# A3 E8 y$ L- ]4 |* ~6 P

0 ?2 u5 l+ w+ R5 O- z5 ^7 H# g
+ X- s9 G* c! i3 T; ?: M* p图1-1 MongoDB架构图

$ C( O4 V. I3 u0 [7 m" f& h
% H7 f/ `5 d. z% W    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。
% A7 w' l. c6 s2 {: O& M
0 t5 Z- B' G2 K7 P5 |Shards
! U, b3 y" J* L+ a
$ B3 k" p1 j+ m% W. L    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。
* I, v8 \5 ]6 w& ^) {& }6 f, |; F9 B- A  a4 h9 F
    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。4 j: y2 S& k5 p
( k# B1 X' I1 c& a! t- k
    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。
- @- }0 ~! ~6 h' [- i: U3 t
+ p: Y7 X# P: n* H. @  R+ A; S    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
) ~; `9 o9 r: a7 Z; F/ M$ t7 [" v4 V, T$ s$ V0 A8 n% p* g
Shard keys+ s3 j# l, v$ w! `2 X; s  z7 U
        4 P' r* {4 C% f3 t( ]8 y9 q- q
    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。7 q, ?5 {' B" d

7 j1 Z2 ^9 z; Z  I  r) r7 o    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,# t# Q5 P8 H5 u6 \9 R7 z! j
6 t. J: a* Y. ]3 a: E( u
{
, q8 ^/ a$ I1 d  "ISBN": "987-30-3652-5130-82",2 T8 ]/ y' B% g3 O& U
  "Type": "CD",
4 K2 Z8 ^. M! U; f. H9 Y, s  "Author": "Nirvana",: G7 z! z3 l: x4 C6 Q
  "Title": "Nevermind",
$ w3 E* i1 ^. j+ O$ l( F/ f  "Genre": "Grunge",; b( W2 q; O8 p: R9 |/ ]6 t: E
   "Releasedate": "1991.09.24",* p7 s! y5 Z9 b: c
   "Tracklist": [
8 x5 ]; K" I9 f( F1 j$ g/ P5 N7 g9 L     {; E: @% |& M8 s9 `4 H& B
        "Track" : "1",! k. }0 Y# ]% U: _- y9 f) S- j
        "Title" : "Smells like teen spirit",1 R. @+ R  g' j0 g# \! v( m
        "Length" : "5:02"
! ^) S$ j* L8 n) {' v5 B; m9 J) W     },  Q3 D- a( m1 w  A1 R7 A
     {! O( ?8 c& s( F
        "Track" : "2",: B& n8 `4 d( U! l5 T) }
        "Title" : "In Bloom",
: `) U* ~# N* }: v+ q5 U        "Length" : "4:15"0 G' g! a- Q+ t0 ^) }9 \9 s" ~
     }
5 h* U$ V. C' M2 q' ^# c6 ?; P# h   ]" S% T& j0 d$ z' T( j
}; p1 }2 i2 I  S' J
1 ^  ~9 P/ {4 \/ X( K( x
{' @* t; G2 Z: }, K. c6 B
  "ISBN": "987-1-4302-3051-9",
2 K% ]# O1 s; o! k2 T" {5 u  "Type": "Book",& a1 C! H! \* W( [  w
  "Title": "Definite Guide to MongoDB: The NoSQL Database",$ c) T/ q- V- F/ b& K+ a- E
  "Publisher": "Apress",; ~# b% h' e# r' e  P4 _6 H; c. q
  "Author": " Eelco Plugge",
  b9 E$ R' F2 N, B2 X$ @  "Releasedate": "2011.06.09"/ X# @& H  ~$ ~$ X3 c9 T' J
}
0 V& q5 X$ s  @9 g$ D+ k0 g
1 }4 }3 c& }) k7 y6 h& L    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。
" o( v# r9 w1 F, q; c( _' j0 Q: G) |+ ^9 E
    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。
, Y. K% C3 l7 k7 `8 i0 d, O9 u1 Z% {+ }6 _) u/ r
    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。
3 W6 y* h# Q( S! Q( m2 Y! \  u! B5 e- c3 {' u0 L$ O( \5 H0 K" y; [7 r
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。! P" a2 x1 P7 t: B* F0 X! Z

. V/ o( M% c- s$ z; \  t) i    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。
- `* `1 t3 `- m  \% Q( R3 o/ o/ e# A0 c$ A# {' _: P
Chunks
2 b/ y/ E: ~* o2 V7 e6 M/ Q        * G0 X0 D1 P. z% Y3 u
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。
, \. W; R" e% M9 a' l4 S) u% z, [4 Y3 D& f* s

0 n; b! P& t: k6 d图1-2 chunk的三元组

' _$ W! e! e3 f
' N9 g% h! ^) N7 l    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。
/ ?7 M' U7 w  o* N( Q* ]( i
: v& X+ Z1 X5 {1 j4 S    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。: V4 S/ R; j7 b7 S9 C

7 |, V( F& T1 n" Y" u- H% V$ v# ~* ~9 u6 A    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。  Y; I4 q" m& X, D
$ |' @( @7 j/ i- ^
    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。
* @& f- W1 T! W' u2 v5 s0 ?( k- h; [* D  C& E$ V4 {
    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。; t0 ^0 x8 W/ ?. \3 n4 [# [  O' U

5 p. M4 Z$ D1 t* Q( l( M    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。
5 T* ?& {- _; h8 b" X& V, |' b; S. w
Replica set
. I: ~+ S3 E2 S0 }7 c8 c- c2 ^! @( O        
6 |# g5 x3 [' t, g1 I    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。5 A" \+ k5 J: L; |4 W+ x

" Z: ~* }, M& [- N+ u' q6 |    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。
8 [( j& }2 x) _& Q+ `+ z" Y. L6 s! f6 J( K0 t# A+ W* D: A/ m* f
    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。
6 i0 a/ j/ X, W" m0 U; q, g9 g' o! z$ E' V9 n2 C3 h3 O
    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。
( D: r  d' [8 \. F6 [$ o( I/ f6 ~/ p* @1 j) L5 o, F% W7 H
Config Server/ O' Z$ X7 s" q5 Q
        
6 k7 w8 A! P2 l    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。
$ [$ ?5 Y  @5 i3 P/ e7 r# R5 K$ |. I/ V3 d- ~. t9 s! K- ?
    每一个config server都包括了MongoDB中所有chunk的信息。& a  b1 A& _4 D

) o, ?4 o# O& A, A! j, G, t    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。
) j: r. ~3 d  I% Z6 r* m3 ~4 a8 u" E- N
    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。1 L# N8 S% N0 n# I5 u  y
8 V3 O0 d$ I, V
    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。
1 S9 J/ D8 P& t
! h4 k7 m, {3 B3 E2 x0 V1 p4 C* K" {9 X/ lMongos( K2 |5 D% v% _( V
( i- H) M8 U% w5 r. Z# }
    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。( M' @/ {6 Y) |
; L# t' _1 Z. y5 ^; b/ S0 r5 [8 i
    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。
, J3 o& |5 L9 R: m0 ~  S, n3 L- v! C% t2 [2 R0 ~
    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。
. Q0 U, K" D7 H% x" l$ X7 y, t: U, [; S: v" W" V( i6 W
    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。
) k0 ?8 d) W3 F4 u1 [2 }$ K8 i( r, ]* t
    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。
/ y- P5 X, ^5 }; x8 g
* ~: P* l/ o8 ]# Z$ C+ B3 g( s( ~( ]0 c0 C
Reference,' G) g8 E# S' E1 X4 h1 S8 Q

6 P0 R6 g8 m! s2 [5 |1 e$ B( d[0] Architectural Overview+ @4 T3 j- G. q4 _1 B  j- ^
http://www.mongodb.org/display/DOCS/Sharding+Introduction
/ d( ]# {4 @1 `0 r+ r
作者: PenPen    时间: 2012-9-18 12:40
本帖最后由 PenPen 于 2012-9-18 12:44 编辑 / s0 L/ q9 g+ ~+ z* N

1 ]& c* @8 @- s: Z4 [& ?0 S' K8 ~4 S8 x% b
您是和邓侃一起写文章的盛楠么?
作者: shengnan007    时间: 2012-9-18 12:44
呃。。。是我啊。。。
作者: shengnan007    时间: 2012-9-18 12:44
PenPen 发表于 2012-9-18 12:40
3 Z, M4 {  `! L7 i3 Y6 ?您是和邓侃一起写文章的盛楠么?
2 Y" z' p& G1 I7 S6 X8 f8 `! R  [) @
是我啊。。。这都能被认出来。。。
作者: PenPen    时间: 2012-9-18 12:47
shengnan007 发表于 2012-9-18 12:44 6 J, C* ]( z' s0 X
是我啊。。。这都能被认出来。。。

' `0 [* z* m1 B7 \8 K' n这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
作者: shengnan007    时间: 2012-9-18 12:49
PenPen 发表于 2012-9-18 12:47 0 {5 n: D1 W/ u
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
# r# A5 C" S2 g/ Z5 [$ c, y
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会员是么?
作者: 不爱吱声    时间: 2012-9-18 12:51
shengnan007 发表于 2012-9-17 22:49 0 S! X& z2 X, o' {
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...
2 U% [5 N" T6 v1 _1 K( ]7 E( V0 S  X
欢迎,欢迎,已经给你变成正式会员了。
作者: shengnan007    时间: 2012-9-18 12:57
不爱吱声 发表于 2012-9-18 12:51
7 x- _" \% Y' U# X欢迎,欢迎,已经给你变成正式会员了。
+ c- J! t+ f1 |: w9 t9 O
多谢多谢啦~~
作者: 巴山    时间: 2012-9-19 03:38
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
3 O* ]( f& C/ e8 a7 s& m
8 x) D% N5 L, h- [) o
作者: 梦晓半生    时间: 2012-9-19 04:21
谢谢。
! z  G% k7 S- Z" f. O+ o; C! t# r" F7 x7 Z6 W: k( T6 l: u
中文看得真累,大部分还是英文术语。
( w/ {# H' {$ }: N5 s- d
  l7 N3 {$ T4 N* n2 q) D" a; `( u这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。
- j4 C+ y- R; ?2 p
+ [. F, W$ m9 x" V# V/ e现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。
作者: shengnan007    时间: 2012-9-19 08:40
巴山 发表于 2012-9-19 03:38 4 I5 \, K4 t% w1 H  c/ r) t5 Z. c6 H
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。1 |6 ^; m: O, y+ _9 |! h

' B5 Y3 s+ s2 A7 i4 R; @+ c* Q* Y ...

( z3 ]0 G& {0 k. ]5 J! k; zmongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的
作者: shengnan007    时间: 2012-9-19 08:44
梦晓半生 发表于 2012-9-19 04:21
9 y! t" H8 t( ~  i: O; P9 t% q谢谢。  A  U/ L+ x9 ]6 l8 t, X( u

6 r7 f# n5 n1 i& H中文看得真累,大部分还是英文术语。
8 r- ]6 u; b# F- g
现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体系。这个系列文章的目的,是让大家了解mongoDB的基本的运行机理,这样以后使用的时候,可以知其所以然。但是由于这方面的资料很少,我也是到处找资料,写了这么几篇,再往后,就是边使用,边看源码,边写了。
作者: profer    时间: 2012-9-19 14:16
shengnan007 发表于 2012-9-18 12:44 : m* A9 ~: O" y
是我啊。。。这都能被认出来。。。

1 `0 b8 Z: E4 q  E; |是邓嫂么?
作者: shengnan007    时间: 2012-9-19 14:17
profer 发表于 2012-9-19 14:16 + W. a; A8 o8 ?- M2 V" }3 |
是邓嫂么?

) f9 V7 t: A$ P. b是邓的小兵
作者: 恶魔吹笛来    时间: 2012-9-19 18:35
有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
作者: 梦晓半生    时间: 2012-9-20 00:57
shengnan007 发表于 2012-9-19 08:44 7 h2 f  Q  m0 A+ Y  C" q# S$ k
现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...
4 ?! l2 [1 R- H2 Z- I; U2 J( a4 i
太好了,期待中,希望都带上英文reference。
( q% o9 v! C! T1 o6 X  X
- h0 b! H' x# ?* x% a% b% K现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。
. t9 G0 l" h# o) b6 e" ^9 R' g" C+ \" _2 Z# n9 y
http://en.wikipedia.org/wiki/NoSQL
作者: shengnan007    时间: 2012-9-20 08:53
梦晓半生 发表于 2012-9-20 00:57 9 P* C/ C" x0 e6 a# H0 @! ^! }
太好了,期待中,希望都带上英文reference。4 l/ I4 m* ~2 h! E1 U7 t

/ S# m- i' x- H' C  v现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...
( D- K  y9 n2 B  C6 V
现在写的也很纠结,资料太少了,哈哈
作者: 梦晓半生    时间: 2012-9-21 11:52
shengnan007 发表于 2012-9-20 08:53 ' \9 W, V. l% B# S3 k% c7 a3 m
现在写的也很纠结,资料太少了,哈哈
- K  O7 [: `, v2 I0 C- [
建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。6 W) R6 M1 }3 @. l
& s$ d+ Q$ F" X1 y$ v4 H% F4 B/ Z
http://en.wikipedia.org/wiki/NoSQL
6 g! @! Y; Y, f9 ~6 a9 v
6 b+ F; O7 m' h% W# u
作者: 定风波    时间: 2012-9-21 17:03
恶魔吹笛来 发表于 2012-9-19 18:35
, j2 D* [  d1 t! g: C3 G有点惊讶 居然在这里看到这篇文章 呵呵 静待大作

6 Y9 E% D: _1 N0 F5 N有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。
作者: shengnan007    时间: 2012-9-24 09:11
梦晓半生 发表于 2012-9-21 11:52 4 p' S3 ]3 u9 A  g  Q$ \+ A
建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
, s* j( t( n! l" h5 D5 Z5 W1 H" d0 S4 h  F. v7 `4 Z
http://en.wikipedia.org/wiki/NoSQL
' V& K  N: A* I' z
好的好的,现在这个写完,然后开始写nosql




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