设为首页收藏本站

爱吱声

 找回密码
 注册
搜索
楼主: shengnan007
打印 上一主题 下一主题

[信息技术] MongoDB架构概览

[复制链接]

该用户从未签到

跳转到指定楼层
楼主
发表于 2012-9-18 12:31:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。
+ H6 i5 ~/ F2 }! ]0 W9 x7 z+ b% e- {8 F3 p0 o
    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?
3 I4 J' H! u3 w' F0 i3 u, {) F# Q
2 c, e5 r: }: ~5 R' z1 \' l    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。0 b3 y  [4 }* `' v0 q% U- z' @

# D9 ^& Q6 o/ f5 o. ]: f2 D0 ^* Y

4 F' m0 z1 c: W  Q1 _
. u% s4 |, E) a0 v图1-1 MongoDB架构图

7 u$ |1 e0 @/ X- j% r6 G  A! W* v! E6 I' O2 p- g- X' @
    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。
1 i, k% _! y2 v: a8 Y4 m9 j3 O3 y' Y6 r0 O, r& g9 U' X; |
Shards
( Z5 Z0 g% i, R. L6 \5 m& H* P8 Q! u: B
    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。# J8 p- T8 V4 X9 `

+ M: }  l- q2 A% X9 v7 c6 ^$ P    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。* u$ W0 `9 \" l! T& S

* v$ H% j" t9 U' B7 Y    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。
  c8 {! s  \$ }# o* Y0 Z0 m3 k2 w7 h9 A. c1 {/ n! j
    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
5 F! \! p% v% l- Y3 ?5 j% B
" u  J/ S1 S' M4 b8 oShard keys. J- A& N4 ?8 R6 t( z9 x- ~7 T& I
        3 ]- t, o$ ~" K
    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。- Z! _0 B2 i6 g- n( P7 A

+ Z, x% p1 M, X1 i, i. R    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,7 e1 I7 J! z' D* u
( x5 a/ x" |: p" ^3 t
{: h; D5 ~9 Z) D" H. @1 Q/ @
  "ISBN": "987-30-3652-5130-82",
+ w- G/ G7 P+ `" A* r! @  "Type": "CD",% K3 j$ K8 `. D) h4 p# [4 a
  "Author": "Nirvana",# ~8 |1 y- T* m# {6 g" O
  "Title": "Nevermind",8 ]" `# E5 w( t! P6 p$ W
  "Genre": "Grunge",% R, l; n1 {6 M/ _5 E1 V6 @  y
   "Releasedate": "1991.09.24",
' P3 J8 E" g) @9 E/ K5 L   "Tracklist": [
$ h. [0 I) h$ ^  e" a+ n4 N# x7 \" u     {
: j7 n' ^" [( A& t$ z6 e4 c1 l        "Track" : "1",8 w1 q% n! Q0 }
        "Title" : "Smells like teen spirit",
. G; R, l3 y1 @' o4 O        "Length" : "5:02"
: H0 N, g4 a+ J/ q+ a, m; d     },$ G$ Y, r6 f# G  l6 y  B/ n
     {
% I: ]8 |7 T9 d. s3 A! F  s+ h        "Track" : "2",$ @. E, O  I2 w$ o5 _' X8 l
        "Title" : "In Bloom",
* z& k; P3 a: w3 Y9 C        "Length" : "4:15"
: M5 k2 P0 b8 ^% j) `9 y     }
. R" U. z5 ^  x! i3 H   ]3 F- M( K: [- ~6 F9 w
}8 ]. R6 Y0 v( {2 G; N; p* b

/ R. P3 o% @: {" u9 O; x{
& i- V/ L' |" U7 J/ M  "ISBN": "987-1-4302-3051-9",& I* X# N# |- p2 M7 H9 _' R, n
  "Type": "Book",- l6 {  T4 D& A( O" d
  "Title": "Definite Guide to MongoDB: The NoSQL Database",
" C+ D8 O+ M% b$ M- ~% D  "Publisher": "Apress",
2 L, S* ?% R: d. C: r6 g5 L  "Author": " Eelco Plugge",4 @) f0 ^, r0 s4 w: a
  "Releasedate": "2011.06.09"
3 M0 r* m: M3 Y7 s. k}/ I  a" }9 t  n3 @$ y5 ]
' p; R( g9 A+ X, g
    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。# n9 J& q3 `; f1 i

7 L6 U$ C/ a, T9 @8 H1 P    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。, X6 x9 O0 r( j1 h# A/ D
" i$ Y5 h; q" x" \5 t1 L# d: e/ P( U
    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。: k4 f' o: N* g
& d/ Z! q( m, d: n+ [. Y
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。
1 c$ T; X7 }) H9 |. @, D0 d) r) N8 U2 E2 W8 U6 v$ F" [8 `
    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。  O4 b1 F" r, o
/ k/ h# _  I! o6 @
Chunks
  R! ~; @& Q1 ?% ?* c  o        8 x# c8 U6 ^( b: B9 l
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。1 S& i: G9 k$ W$ c3 q+ T3 F' i

9 [* y& M$ a% w9 m

% w9 d* [2 l& J3 _5 m- {图1-2 chunk的三元组
/ T% V% \  l& h- |4 T, T

. p2 Q4 o8 x8 l    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。$ c4 F& N  e: v( Q; i" L1 l+ x
: t6 W+ c9 w. P- `& h+ m7 M- ^$ t3 B! v
    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。
9 v( ^; p( D. G, X6 _
# F3 ^  C/ I- B& k- m" n9 ?    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。
. Z: R% f3 e4 b+ j* ~! R
7 V- h0 X4 K# k7 t- V4 a$ m5 P3 X- h$ O    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。& Y) s) I% {% ?7 {: J6 A
4 t7 H1 C  o# K" T* D  e1 P2 L
    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。% B! k6 l0 H1 y4 @5 v# F% }

$ w6 b1 M# @) U8 {4 g    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。1 ~8 p0 P% t0 Q: b0 Z9 l6 _2 i' w$ t0 Z

! v. ^) @7 p$ i, W. L# x6 ]+ jReplica set$ q6 @$ e' Q1 ^# ~+ ~; X
        : u6 A4 E  X, z' t- @" ]
    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
" l* M( T# D2 i. j
( D- e+ [8 t+ ]; K: h* I# n3 Z0 Y9 y8 R    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。
" o8 p9 O  F) U9 Y- q
$ G( S; j& e% ^; o; k    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。
$ M. n" f) K) K2 M# O1 }8 }, s; B8 n0 p% H& q8 {2 {* P0 W
    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。9 z# ^: R- X! u& O  t! z, ^3 ?

2 [2 z# R9 d7 R- ~! Y8 zConfig Server& |) w: @" G2 W$ K
        & k9 i: Q3 D3 L
    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。
( Z7 ^; G* Y1 }9 W: G( \( Q4 Z7 N0 v7 I
    每一个config server都包括了MongoDB中所有chunk的信息。" W: f$ S- y. B: @+ o

: U* ^, T% J5 H4 w  \! j    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。0 k! k/ F/ `/ j- n+ g6 n
2 Y: r; `/ B& j# i6 V
    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。) ?* ]  [( O) Q5 d9 G$ O

: R8 _8 {# p7 v" _    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。
5 p" z( o  A" `2 K6 u7 P# Q5 ], J0 C- W* `: P9 }
Mongos
+ B: s: |6 L7 e9 `" R1 X9 \! ^/ r# Z' g1 y$ l! Q$ ?
    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。# d: j8 A: g- ]0 _! K4 o( |

! W  G8 K. s0 T    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。! ~$ P# x; ~% a3 f

6 d( y5 t* i5 Z    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。+ j( {- ^' M# [

- u# M% {# M4 E# @" n1 Y  h8 x    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。+ _1 U" n  D, X* C2 Y7 m

) ~' _9 O# n; v& ]& b2 p    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。; z6 r$ g( R4 V$ Y8 f) t
4 @% [9 q& o0 J+ o2 X
+ @9 W: `5 d/ ?: q# ?, d9 {- Q* E
Reference,0 H* J8 [! Q2 g! ^( }' B

& z. L$ ^, o$ o, q0 F, G% n[0] Architectural Overview
: P1 }! i' }9 o& n7 u% s6 ihttp://www.mongodb.org/display/DOCS/Sharding+Introduction
# B: d6 D- w6 v! e

评分

参与人数 1爱元 +10 学识 +5 收起 理由
不爱吱声 + 10 + 5 谢谢!有你,爱坛更精彩

查看全部评分

该用户从未签到

沙发
发表于 2012-9-18 12:40:50 | 只看该作者
本帖最后由 PenPen 于 2012-9-18 12:44 编辑
* ^& C% p/ o& c0 Q) m
) Q- s( R0 |5 b
/ V$ ?; u: v0 _您是和邓侃一起写文章的盛楠么?

该用户从未签到

板凳
 楼主| 发表于 2012-9-18 12:44:19 | 只看该作者
呃。。。是我啊。。。

该用户从未签到

地板
 楼主| 发表于 2012-9-18 12:44:45 | 只看该作者
PenPen 发表于 2012-9-18 12:40 / w* F7 Z- L, j" L
您是和邓侃一起写文章的盛楠么?

; N0 o1 C# Q/ M8 O是我啊。。。这都能被认出来。。。

该用户从未签到

5#
发表于 2012-9-18 12:47:20 | 只看该作者
shengnan007 发表于 2012-9-18 12:44 9 s9 o$ k  n) f& f) v1 G
是我啊。。。这都能被认出来。。。
* c' y6 ?% l+ G1 m) u+ i! C
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

该用户从未签到

6#
 楼主| 发表于 2012-9-18 12:49:50 | 只看该作者
PenPen 发表于 2012-9-18 12:47
7 [3 h5 P. t+ l. y这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

  v- w2 |1 ~" h2 `/ A3 _多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会员是么?

点评

你已经是会员了~  发表于 2012-9-18 12:50
  • TA的每日心情
    奋斗
    2022-2-8 01:13
  • 签到天数: 171 天

    [LV.7]分神

    7#
    发表于 2012-9-18 12:51:42 | 只看该作者
    shengnan007 发表于 2012-9-17 22:49
    ( s; f6 E4 `, R5 h多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...

    # j, P2 K- G/ W欢迎,欢迎,已经给你变成正式会员了。

    该用户从未签到

    8#
     楼主| 发表于 2012-9-18 12:57:15 | 只看该作者
    不爱吱声 发表于 2012-9-18 12:51 9 r0 B0 b& J+ l5 S/ G* X
    欢迎,欢迎,已经给你变成正式会员了。
    4 Q; P* M& v! ^6 r
    多谢多谢啦~~
  • TA的每日心情
    慵懒
    2020-1-15 02:37
  • 签到天数: 1287 天

    [LV.10]大乘

    9#
    发表于 2012-9-19 03:38:34 | 只看该作者
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。" g& W* ~% u  q% y
    / n8 _! e! ^$ k; Y* g6 F( Y

    该用户从未签到

    10#
    发表于 2012-9-19 04:21:40 | 只看该作者
    谢谢。. Z, h& _% y5 A9 X% O
    0 [; b- o$ C# q- Q
    中文看得真累,大部分还是英文术语。% E& v8 j- _& @* [! O4 |( p8 M* j6 {6 j

    " D8 {" o0 x5 T; a1 V/ H" T/ n1 A这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。4 I' ^' }- ~7 Y% Z! U- q' ^

    . E8 z, [3 R$ p/ T+ }) ~  i现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。

    该用户从未签到

    11#
     楼主| 发表于 2012-9-19 08:40:52 | 只看该作者
    巴山 发表于 2012-9-19 03:38 ( l) ]7 @5 x! Q6 K; x7 h
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
    7 @) D+ D% X/ g% y# C) m2 |* y: B( m% f, b6 O* x$ B1 R! N8 l0 o" g
    ...

    0 L8 g9 W/ s1 P; }4 }5 pmongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的

    点评

    主要是transaction acid的问题。  发表于 2012-9-27 17:12

    该用户从未签到

    12#
     楼主| 发表于 2012-9-19 08:44:52 | 只看该作者
    梦晓半生 发表于 2012-9-19 04:21
      _6 I1 V+ p' N0 G- f1 q6 T8 c4 Y6 b谢谢。5 ]4 h. C1 J, A5 q( f6 L) D- Y
    1 J7 v1 m1 ^$ i) m: G+ d8 u
    中文看得真累,大部分还是英文术语。
    : o  O, o6 ]+ u& l" B$ ?
    现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体系。这个系列文章的目的,是让大家了解mongoDB的基本的运行机理,这样以后使用的时候,可以知其所以然。但是由于这方面的资料很少,我也是到处找资料,写了这么几篇,再往后,就是边使用,边看源码,边写了。
  • TA的每日心情
    奋斗
    2018-1-6 00:24
  • 签到天数: 1 天

    [LV.1]炼气

    13#
    发表于 2012-9-19 14:16:01 | 只看该作者
    shengnan007 发表于 2012-9-18 12:44 ) y( {( y' S9 b  }$ G
    是我啊。。。这都能被认出来。。。

    , {( F' M  C  H: x9 L) s4 M6 K是邓嫂么?

    该用户从未签到

    14#
     楼主| 发表于 2012-9-19 14:17:53 | 只看该作者
    profer 发表于 2012-9-19 14:16 / S4 I1 Y+ @0 e
    是邓嫂么?
    $ O2 R& G/ {$ D. {
    是邓的小兵
  • TA的每日心情
    奋斗
    2019-9-9 20:24
  • 签到天数: 1 天

    [LV.1]炼气

    15#
    发表于 2012-9-19 18:35:28 | 只看该作者
    有点惊讶 居然在这里看到这篇文章 呵呵 静待大作

    该用户从未签到

    16#
    发表于 2012-9-20 00:57:50 | 只看该作者
    shengnan007 发表于 2012-9-19 08:44
    + n: T8 [3 X. d5 d现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...

    ) ^% V5 ~) f% \% s# e太好了,期待中,希望都带上英文reference。8 D2 I# d" M- l5 k! h; Y( t. c" b

    : M  i3 N2 X! ^9 j! T  @/ ], f现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。
    " N+ o7 x+ ]$ C9 k4 W( c3 y1 L; r1 @- s$ b
    http://en.wikipedia.org/wiki/NoSQL

    该用户从未签到

    17#
     楼主| 发表于 2012-9-20 08:53:41 | 只看该作者
    梦晓半生 发表于 2012-9-20 00:57
    2 r3 I& `. j+ F' n太好了,期待中,希望都带上英文reference。. p/ Y; \2 N! X4 k7 W* G

    , ~0 c9 i, l# R5 T/ \4 O# I现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...
    & }6 j+ i, K. C9 M
    现在写的也很纠结,资料太少了,哈哈

    该用户从未签到

    18#
    发表于 2012-9-21 11:52:33 | 只看该作者
    shengnan007 发表于 2012-9-20 08:53 8 k. x3 i4 c3 H3 |( E2 L6 C
    现在写的也很纠结,资料太少了,哈哈
    2 Z# t; D9 E9 `5 x6 i; _
    建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。5 Y  ?6 R+ t# b2 C- F; f# h) @/ v8 @

    0 D2 C4 u/ ]6 v6 e; p6 l: Nhttp://en.wikipedia.org/wiki/NoSQL9 q4 `5 h1 i6 [4 u9 h: i- x

    $ \  V! i1 k0 A7 u2 ~: W" n8 ]
  • TA的每日心情
    郁闷
    2019-4-22 08:49
  • 签到天数: 38 天

    [LV.5]元婴

    19#
    发表于 2012-9-21 17:03:12 | 只看该作者
    恶魔吹笛来 发表于 2012-9-19 18:35
    + k# V9 r- A6 t+ w# K有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
      t: h$ g) C2 k% t: }$ U
    有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。

    该用户从未签到

    20#
     楼主| 发表于 2012-9-24 09:11:03 | 只看该作者
    梦晓半生 发表于 2012-9-21 11:52 / n- T. L/ B, A; q: [+ U# _
    建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
    % G+ F1 g' D' c9 t9 ^
    6 Y* ~4 \2 h5 u  U  f- |- R8 u9 fhttp://en.wikipedia.org/wiki/NoSQL
    * X3 p% S1 @# t4 U
    好的好的,现在这个写完,然后开始写nosql

    手机版|小黑屋|Archiver|网站错误报告|爱吱声   

    GMT+8, 2025-7-2 12:46 , Processed in 0.058534 second(s), 21 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表