设为首页收藏本站

爱吱声

 找回密码
 注册
搜索
查看: 7553|回复: 19
打印 上一主题 下一主题

[信息技术] MongoDB架构概览

[复制链接]

该用户从未签到

跳转到指定楼层
楼主
发表于 2012-9-18 12:31:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。. @9 \4 v3 |" D
9 W1 j. R3 U5 b4 L% @
    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?
! ~( ^% K, W" L
, I( F( f$ L' s* Y    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。
$ u4 U% V5 l$ k; ~9 o0 I) b9 M5 c
9 ]( n0 v" c  t7 l. J

- r/ l% V6 z+ V5 N  G; K$ S0 W- x
3 b* \' _9 C' f) y" z1 A图1-1 MongoDB架构图
! Z- ]& q5 H) N' W: F9 ~/ ~6 _
( }& m% R& S8 _7 ?
    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。+ m7 X% w3 a( @4 @/ Q% u
7 l+ P! r5 B% k7 @" l
Shards. }( r9 f' c* m2 k0 v
9 q9 v/ |6 S8 a, A0 g
    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。9 V/ _2 q8 t5 b  q4 u1 l% t3 \6 `
- p+ }  P! _' d
    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。9 ^% P, x: y7 R: b8 b$ p8 B+ ]

) l* n% z5 F9 X& m/ N' W$ S* r    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。% p- c: E! }2 G3 l  d
/ f: l* ]0 [1 A6 W
    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
, v% Z' a$ |: {
8 L; W  s2 c4 zShard keys
8 u) T0 O" d. R# t        
4 G0 R4 g, k  I/ |    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。
) y5 @6 p( C0 i1 Z4 Z- t
, V* P. R" E& h: ~4 T% X    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,
5 P1 I: K: }+ J) m
  w( p& x  x+ v( D{9 l- q- ]1 ^( u4 P. g& g
  "ISBN": "987-30-3652-5130-82",0 n. \6 M2 e5 w/ l+ _
  "Type": "CD",
( n6 ]" x4 U- t) S: d/ C; A  "Author": "Nirvana",
% d2 Y: E! j$ ^( a2 N" T% J  "Title": "Nevermind",
1 p# |) a" I! Y/ V7 F' Z  "Genre": "Grunge",; K; }( P5 U, m& q
   "Releasedate": "1991.09.24",4 O& S5 n5 S8 _
   "Tracklist": [
. p% g7 T8 G/ U     {
/ r4 W/ ]9 s; p" m        "Track" : "1",+ j; _- A0 ?, s3 P6 [% f5 q) u, [! r
        "Title" : "Smells like teen spirit",
7 ^6 ]5 ?3 B, Q- H9 o# H7 S6 b        "Length" : "5:02"$ P# w6 l' J8 f4 ]# F( S& `+ O
     },& \& W# w8 R8 Q4 S1 D( f" m
     {  d; f# @& U( u+ {; A1 C
        "Track" : "2",1 T! E& y8 }! Y  O- l
        "Title" : "In Bloom",2 D( A; J7 ?2 |- s
        "Length" : "4:15"
' {7 E' }  l  Q  {9 |- E     }7 W1 ~8 l( w/ h, k3 }6 J
   ]
9 K  l& e0 f+ `' t: Q( A" }}
) `8 G; X$ S+ u! R; W" Q9 O6 N( ~: g* U; b
{" T& [/ \8 m9 T* c' o
  "ISBN": "987-1-4302-3051-9",
! M7 C' R2 s- l) u. X  "Type": "Book",
- M. T" a5 V& D- d  "Title": "Definite Guide to MongoDB: The NoSQL Database",
9 S* x* t3 K- ?4 L' u: C4 q- K  "Publisher": "Apress",+ h9 i! R, l) o8 ]; x5 P( I+ W
  "Author": " Eelco Plugge",% E2 g, L/ M) {/ m4 @. S6 Q
  "Releasedate": "2011.06.09"
- s3 P, ^, k( c" Z/ M3 B! d- V}: N6 f; x( R% G$ ~& A. g9 O
- E6 D* g& y$ |& A4 W* `7 w
    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。+ K( y+ z  ]; i" i0 ^0 D
) E2 O0 c3 M0 i/ `3 |
    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。
: ]! v' L( K1 S9 @  l* }$ [# B% l5 q' O3 F, b- x. H
    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。/ u4 O: q- d- U9 w
9 _) Y: [+ D( `
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。( f+ h1 F: n( G5 [) v0 G
+ Q  |5 y) I0 F2 @2 A1 `
    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。% s) y! X3 D% W$ o1 m
$ q7 d# C4 d$ n1 z$ W) q
Chunks7 [. ]' B7 ~- q
        ; w# K' Z2 Q3 |! }
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。
+ n0 E6 i) k: l# A; g
1 X) A1 x4 ?7 i' A% S

. o* ?" p  U1 ?5 }图1-2 chunk的三元组
! U5 \$ m' o6 U

7 V6 u/ I; o  u1 ?    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。
4 I0 x, Y, \% G
" v5 Q9 _( K. ^& E- Y- c( L    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。, x: ]# u# e+ ~4 S

5 y2 V+ d: g9 _+ x  R: `    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。
4 S* \. {( G' e" {) ^9 u6 c  J! }* X' d
    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。
$ f/ y: r8 I7 j7 g1 r3 V8 Y- n+ W) p5 b# r. U
    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。
+ e3 }2 a( g( g, w% o
+ j0 w4 O0 B5 ^9 m4 c    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。
  j5 R3 g3 f  ~/ E3 @
# ^" h) l. b' H" M1 n6 o) P4 xReplica set4 k- _4 n9 n1 D' k) @
        7 \6 x9 a- x$ _% b( ]4 q2 }- C
    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。0 ?. s0 g" s3 M! F+ w% p

4 e% F$ r7 S% A9 W/ I* m2 Y    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。
' `! g7 G3 z$ |; T- t2 k- Z; }' M% v$ ?9 \- w
    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。
7 b4 l8 W% `% D  ]- @2 [
3 R! Z  L2 f  w* I) t* Z/ H: q; b    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。
$ c0 u  b- ?6 w( f% o0 `
0 R1 ^# R+ m% UConfig Server- d. C$ l. R; n2 O
        % K0 y0 {8 @; o& U  E) t1 d
    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。
7 n9 y8 Z0 A" q# v- \. E: s* k
1 i5 Z2 e3 U8 D3 \& `; ]    每一个config server都包括了MongoDB中所有chunk的信息。
. H3 P/ w5 G9 P" f" v$ p
) h* ]  E% S* v4 g3 J- o6 r    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。
5 I& l& ^3 E2 R  }0 I2 }& `( }& Q- |
    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。
) t2 j- m/ I5 G4 e$ d( c1 _) Q' w; Z9 Y: o& s1 C  k. {
    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。" r1 a% C2 L, U
3 [% U) M6 P1 R5 K0 _6 @1 }- u# H
Mongos* [9 m, z9 f) v+ U+ q3 k

, ^7 f& Y- y# R" f6 p8 T/ T    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。
* T$ ^2 [5 p6 T, `7 n& v9 Z& Q* v
    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。
6 n2 B' N+ I: _# e
# G) w; ~% e* N# Z, e4 `    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。
7 w$ |$ N! s( d! z# L% {' x. \5 w8 d7 U4 R$ N, P
    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。
$ U7 w0 B! N: L$ X$ A) g0 S1 d7 {# |$ w
    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。
* ~( v' s9 O; P& ]: `
, x1 m& }  H! R8 [4 B2 X# k! u4 o+ M$ S5 F2 F( C& P
Reference,. |, `- D& H2 L+ b7 J* J
+ g  }" m0 w% Y
[0] Architectural Overview* G) P1 o( U' u2 y: r8 `( R
http://www.mongodb.org/display/DOCS/Sharding+Introduction
7 u' \# m; Z1 |

评分

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

查看全部评分

该用户从未签到

沙发
发表于 2012-9-18 12:40:50 | 只看该作者
本帖最后由 PenPen 于 2012-9-18 12:44 编辑
" N. O; v/ K* D6 H' G/ |
" J# Y/ g  T" J! `: X+ {
2 f4 L+ B% D: m$ Q. J( {' @  _# `您是和邓侃一起写文章的盛楠么?

该用户从未签到

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

该用户从未签到

地板
 楼主| 发表于 2012-9-18 12:44:45 | 只看该作者
PenPen 发表于 2012-9-18 12:40 ( i! p. e' a3 i9 Y
您是和邓侃一起写文章的盛楠么?
- Y8 \/ t9 R* ?" v3 O+ q! F
是我啊。。。这都能被认出来。。。

该用户从未签到

5#
发表于 2012-9-18 12:47:20 | 只看该作者
shengnan007 发表于 2012-9-18 12:44 & M6 [% M, O# X0 A* j5 [) W( m! ]
是我啊。。。这都能被认出来。。。
6 ^) N+ w: P6 {  r; \! b
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

该用户从未签到

6#
 楼主| 发表于 2012-9-18 12:49:50 | 只看该作者
PenPen 发表于 2012-9-18 12:47
  _$ ?( @, p3 R# i这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

. a: F" {% }2 d* u/ N! B. u多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,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
    ( n9 ?8 ~8 @$ _( G. o- @% ~1 P多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...
    # j9 h0 E% f+ ]
    欢迎,欢迎,已经给你变成正式会员了。

    该用户从未签到

    8#
     楼主| 发表于 2012-9-18 12:57:15 | 只看该作者
    不爱吱声 发表于 2012-9-18 12:51
    : I% y2 i5 s! B: p欢迎,欢迎,已经给你变成正式会员了。
      u) v9 a2 d+ q6 [" W
    多谢多谢啦~~
  • TA的每日心情
    慵懒
    2020-1-15 02:37
  • 签到天数: 1287 天

    [LV.10]大乘

    9#
    发表于 2012-9-19 03:38:34 | 只看该作者
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。7 P8 e7 g/ E. i) Q$ u. q& A
      y7 x: d$ N. R# _$ ~

    该用户从未签到

    10#
    发表于 2012-9-19 04:21:40 | 只看该作者
    谢谢。
    . T. h8 k$ b1 A  _5 ?
    / s/ t' s- G) K3 c: ^( k' o$ q# ?中文看得真累,大部分还是英文术语。: W: G2 u  h9 j: D

    ! N( e: i, b. G这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。
    8 k5 O7 _: ~4 e" w0 b2 G9 O
    " H) d0 e) s' |+ {! h现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。

    该用户从未签到

    11#
     楼主| 发表于 2012-9-19 08:40:52 | 只看该作者
    巴山 发表于 2012-9-19 03:38 ( a/ Q9 K8 z  w+ _
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。4 x: o* J0 E: V* q" l
    9 {* ]/ e* T9 p- Z
    ...
    9 ]7 }+ l6 j  W$ A  \4 \" }5 H) o
    mongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的

    点评

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

    该用户从未签到

    12#
     楼主| 发表于 2012-9-19 08:44:52 | 只看该作者
    梦晓半生 发表于 2012-9-19 04:21 / Z9 C4 A6 F) e& g( {; `8 o! I
    谢谢。
    * ^; x* H- q/ u1 e9 z- R
    % d7 b( H+ |: d3 Q& c' X9 P中文看得真累,大部分还是英文术语。

    ' U& Y6 N: m  W' F3 n0 ?4 m现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体系。这个系列文章的目的,是让大家了解mongoDB的基本的运行机理,这样以后使用的时候,可以知其所以然。但是由于这方面的资料很少,我也是到处找资料,写了这么几篇,再往后,就是边使用,边看源码,边写了。
  • TA的每日心情
    奋斗
    2018-1-6 00:24
  • 签到天数: 1 天

    [LV.1]炼气

    13#
    发表于 2012-9-19 14:16:01 | 只看该作者
    shengnan007 发表于 2012-9-18 12:44
    & p2 [. w: V! R, V2 k, Q8 `是我啊。。。这都能被认出来。。。

    7 e1 R* T; h5 l0 e+ \' K是邓嫂么?

    该用户从未签到

    14#
     楼主| 发表于 2012-9-19 14:17:53 | 只看该作者
    profer 发表于 2012-9-19 14:16
    7 \. ], P, u$ o, a/ C是邓嫂么?

    6 m8 n* E8 J/ G1 |8 @是邓的小兵
  • 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 ' c6 w+ W5 w) ]1 F0 N  }
    现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...

    6 L9 R! o% S$ p太好了,期待中,希望都带上英文reference。( Y- a( O5 k; X7 Y  d
    7 o- r2 |3 G& X
    现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。
    0 Y& ^( [" g$ p9 F5 h# o- h
    " Z5 j1 U: M! D& j; j4 Hhttp://en.wikipedia.org/wiki/NoSQL

    该用户从未签到

    17#
     楼主| 发表于 2012-9-20 08:53:41 | 只看该作者
    梦晓半生 发表于 2012-9-20 00:57 1 K& X( v! I* d2 p
    太好了,期待中,希望都带上英文reference。
    ( p% K2 A0 Z, ?1 k, [- Q7 X6 [' q3 S9 k- A$ [) a2 G
    现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...
    + m& l. o# E) h- a! A
    现在写的也很纠结,资料太少了,哈哈

    该用户从未签到

    18#
    发表于 2012-9-21 11:52:33 | 只看该作者
    shengnan007 发表于 2012-9-20 08:53 $ l- V( w/ p5 O" T3 a: e( h
    现在写的也很纠结,资料太少了,哈哈
    6 n% _5 y4 [0 T" b# k8 ]
    建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
    ; K+ x- }& |% O0 N2 j9 H' m
    0 s- _; \$ @  d6 _* V. Chttp://en.wikipedia.org/wiki/NoSQL" Q- x  i4 H/ ]& Y7 G: a

    9 L* b7 q$ p7 w0 C- t
  • TA的每日心情
    郁闷
    2019-4-22 08:49
  • 签到天数: 38 天

    [LV.5]元婴

    19#
    发表于 2012-9-21 17:03:12 | 只看该作者
    恶魔吹笛来 发表于 2012-9-19 18:35
    ' |, b* q. E- P; H7 u有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
    4 C% E" d+ K" I3 m
    有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。

    该用户从未签到

    20#
     楼主| 发表于 2012-9-24 09:11:03 | 只看该作者
    梦晓半生 发表于 2012-9-21 11:52
    8 `8 B: @+ M0 Y2 x& J5 K7 k建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
    . f3 A1 h0 O- h2 `# q$ h: o/ q* c) O3 T6 E8 i) |, t7 _  H9 ]
    http://en.wikipedia.org/wiki/NoSQL

    0 x, q1 t; k: o/ X: Z4 V0 ^好的好的,现在这个写完,然后开始写nosql

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

    GMT+8, 2025-7-14 20:56 , Processed in 0.051807 second(s), 21 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

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