设为首页收藏本站

爱吱声

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

[信息技术] MongoDB架构概览

[复制链接]

该用户从未签到

跳转到指定楼层
楼主
发表于 2012-9-18 12:31:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。* O' z* a1 Y: F* N
- s' w& R  N: h" O% H" I4 z% ?% t
    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?  P. O7 A# X* q# o

1 `9 H( b( L) V* K/ j1 x# M    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。
4 q5 w+ D6 S  t! ?/ _/ q2 v  w. f) d  `

- K' Y2 [  E3 _/ @( x6 o+ Z6 o5 @- x. ^$ p+ Y9 e
图1-1 MongoDB架构图

" w5 x- t) A* e% ]8 h, a$ v
) a( _# f" [6 @' {& P    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。6 ~4 l/ A! s& J8 r1 w

7 O  N* n4 c$ S+ p7 eShards4 V6 b' Z1 {: b6 f+ u4 Q$ \8 W

2 E( ]* j& V5 S3 t; I7 Y    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。; x( K7 m* z4 j8 A6 C- P4 K6 ~9 n; F: ~$ a3 o

: r* K/ X* _7 l( @+ ~    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。2 I9 Z& |2 I5 R( J
7 }) F  A9 d; Z9 ^0 r" s
    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。
( W  H/ i5 x9 s/ N
' ^' v1 h$ ?4 ^2 [* x    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
% {! o8 W" Y6 f( \% ~: h" N0 l# r! O6 c- y5 N( Q
Shard keys" I' A0 A/ o) B+ Y' H% `
        
5 K6 ~  N! d. J' @7 ^  C- o    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。
. M" H  q+ k- N% O2 z' R6 c- @  j& B
    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,/ O/ z* r1 f. D6 T1 V9 s) t. I

8 [% B2 L8 a0 ?7 z; h0 i& L{  e" M  t: ?) W
  "ISBN": "987-30-3652-5130-82",
- {$ \6 v6 u2 Y5 |1 i% s6 ?' z( Z  "Type": "CD",$ J) r" o3 J+ }/ k! X
  "Author": "Nirvana",* Q- R; Y' a* D0 }- H! R
  "Title": "Nevermind",& g* F0 ^* h8 K* A) l# K
  "Genre": "Grunge",
: t+ B$ b! [: s) C! i   "Releasedate": "1991.09.24",
* E- t: I; S6 J7 ^   "Tracklist": [
" Q' `+ Y- e( Z( t. l     {
6 V7 G! S: t# |, l; c0 h0 _        "Track" : "1",0 ?5 I4 l0 P5 h9 m& q7 A
        "Title" : "Smells like teen spirit",
' {7 }, z  D, H! C0 x- F& |        "Length" : "5:02"
# r$ N2 G7 Z, S2 U1 e5 D' a     },6 C7 M9 A3 s+ m9 @% y3 i4 O4 T
     {: h+ S4 G! u1 `4 w6 V
        "Track" : "2",' H2 r7 P' {/ w+ r$ U
        "Title" : "In Bloom",
& K( i, o5 Y8 ?  o$ H        "Length" : "4:15"
* V) Y* e; f. s3 p+ w# r     }
; q& {1 S1 H! R% D   ]* H; D1 L# a) @3 T9 t
}
4 k5 C2 s% I8 ]7 D$ V) n+ _
' p2 l6 u2 a7 r4 B& D' \9 t) K( q{
. K: y- V& U% n9 I% F6 i2 [! w; q  "ISBN": "987-1-4302-3051-9",
; s( T/ D5 ^" o+ r+ ^* u# U; \  "Type": "Book",' o: }, N7 t0 a+ w8 m/ k# G% [0 v
  "Title": "Definite Guide to MongoDB: The NoSQL Database",4 l" k) Q4 g* M
  "Publisher": "Apress",
4 k( J6 S, _- B  H; |  "Author": " Eelco Plugge",7 ?! C$ F  D# R" ^
  "Releasedate": "2011.06.09"
5 l  z+ l# [7 @8 W}* s. M3 ?! ?. ^* j+ \: O

, {- \& s1 }3 s& X  r    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。
. B4 L1 ?2 B$ L
! A# ]( f' f% M2 |# U( d    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。  O, s- y" ~- V
  }/ r- F/ ^, k9 N1 q4 @: ?
    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。. s8 `; _, U/ q, T: X
* a* \7 y! ^" E' g$ `+ f- r
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。) K. G4 j+ g6 O: t5 k: ^% ?% b
8 {# b* s4 B+ y( _. b
    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。2 P6 h* o2 x. F$ [7 M6 {
* E+ Z7 m% G) s5 i% a4 y& w+ X9 e  k" p
Chunks) n( v( o" M* k1 P& `4 Q# A
        4 Q) p* b6 y0 F
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。
; w4 v" ?. k$ i: @; Q
9 W& o/ j0 E+ r; L3 F7 u+ B; Y

& m; Z' d4 i  m9 G图1-2 chunk的三元组
* z* t2 S* l  Q

0 Z. O% O, ]: E" M8 o6 `$ Z5 m    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。" i/ [6 ~7 S+ M5 g+ \9 J
+ U: [$ b; p* `) ~+ X
    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。& P& H5 l6 T# x9 k, E

, M; z; z) Q8 M2 q( s    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。4 U# N+ w  B6 ?, L

  _! @( k% v8 ~    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。3 v! R! ]" t: {* D6 I

/ R& S" \6 {# z) d9 c$ r. F    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。  b4 a. S8 i3 V" P+ W0 g

& k* |: s4 G: i    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。
; j8 a, |+ ?9 j. U" u* v/ v6 F" n9 J8 C
Replica set# y$ [+ l) n2 f0 U2 V; x8 _0 _
        
7 y  a# w) \% ^! r! r5 O6 a" @7 N    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
$ [1 w* a! y, W6 ~1 A( t& F
' Q% `. l3 V8 H    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。2 [; o- b0 C% q& B' c( N/ A" a' L- U3 h
" y* ?+ F( t1 V3 B6 V6 ~
    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。
3 w4 {0 C4 S9 E, w1 M% [! y+ _: w# P0 S6 E
    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。( \2 F( J1 E/ `3 f
  E$ |: X- j: a$ e4 i
Config Server- ~$ T# {) z) e" U2 @2 K
        
2 m2 G5 h, o4 L( P+ h1 b    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。. k; L! h& s" E! {# f8 G: c6 r# m, c

% M8 o, t: O: O# W9 k" p5 ^    每一个config server都包括了MongoDB中所有chunk的信息。
2 z& W# x& w; ]( V, z: a% w# c4 G: C! W7 n3 Y% R
    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。/ r( j1 q8 [" a& Q( D
" C6 M6 l# B; k! Z6 e
    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。* R. d, T( r6 ]& F! r
' m# y. C% `' V$ k6 j/ H& |8 U0 K
    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。
3 q( o* Y$ i. ?1 K/ w. Z8 |+ n/ H/ y* N; h4 I) w( A
Mongos+ S+ A- W. q# I0 R' ]

$ v1 G7 P! x' `' V- q, b    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。$ A! E0 h" U3 f; F1 P0 W

+ ~- i/ j% d0 Z. c. {- D) k    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。
" r" o* j6 Q4 [- U' J" i5 U9 `) r8 P# g( E) K/ B6 Z
    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。$ k' _5 U" [% I+ w  t: L
6 Q" `8 G: ~- i/ ?
    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。1 }( T/ B: [9 U$ V& s3 I2 z

) [5 {5 \, m! F" Q! @9 z: m+ G    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。" W7 E1 n9 y1 l3 l2 {) X7 D
: {/ \0 S* U- T, \0 p8 f' Q

2 t! f  g  L# y% _! k5 gReference,
/ n' H7 H# w; E) w3 v  T# G
/ G6 m' k7 L/ _0 V: L2 K- U( z3 j[0] Architectural Overview
* e6 l% J/ G2 O& Q8 H9 I/ w! Rhttp://www.mongodb.org/display/DOCS/Sharding+Introduction" m1 F( T4 _0 G0 m, Z! k6 u4 d

评分

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

查看全部评分

该用户从未签到

沙发
发表于 2012-9-18 12:40:50 | 只看该作者
本帖最后由 PenPen 于 2012-9-18 12:44 编辑
" e9 L9 R; e! a( J: v7 z8 r
' A# q/ N( b% J. S
% D' b3 P# K1 ^' {- e您是和邓侃一起写文章的盛楠么?

该用户从未签到

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

该用户从未签到

地板
 楼主| 发表于 2012-9-18 12:44:45 | 只看该作者
PenPen 发表于 2012-9-18 12:40 . J1 M( R' v  s( ^: k
您是和邓侃一起写文章的盛楠么?

* m4 B6 z" ~) r$ T$ Q% @是我啊。。。这都能被认出来。。。

该用户从未签到

5#
发表于 2012-9-18 12:47:20 | 只看该作者
shengnan007 发表于 2012-9-18 12:44 3 k* N7 A; }8 w6 f& |( X
是我啊。。。这都能被认出来。。。
- k1 v6 X" \4 N! V- ~. Z
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

该用户从未签到

6#
 楼主| 发表于 2012-9-18 12:49:50 | 只看该作者
PenPen 发表于 2012-9-18 12:47 0 \8 `& |  [+ D9 }3 p2 x( y8 I
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
6 b6 b: A' K5 I- J
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,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 9 ^# K7 E: H5 @
    多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...

    , _- f- l- f+ }4 K! r4 d欢迎,欢迎,已经给你变成正式会员了。

    该用户从未签到

    8#
     楼主| 发表于 2012-9-18 12:57:15 | 只看该作者
    不爱吱声 发表于 2012-9-18 12:51
    / y5 G- @5 k" ~$ z/ e, y1 F欢迎,欢迎,已经给你变成正式会员了。

    " P; u1 v7 x( v- `* Y. r9 d多谢多谢啦~~
  • TA的每日心情
    慵懒
    2020-1-15 02:37
  • 签到天数: 1287 天

    [LV.10]大乘

    9#
    发表于 2012-9-19 03:38:34 | 只看该作者
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
    $ {! k) a8 v% A! z
    1 x1 K2 P" t; B

    该用户从未签到

    10#
    发表于 2012-9-19 04:21:40 | 只看该作者
    谢谢。4 z4 d- r* B) k* A( u

    ' T, O6 j. v3 Y中文看得真累,大部分还是英文术语。
    ' B2 J3 `3 u) @) L" ~* O% U5 i3 a1 S& y5 V
    这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。
    * W1 q3 A0 z0 W+ P9 }/ I+ b0 P' T( i4 [, O7 g
    现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。

    该用户从未签到

    11#
     楼主| 发表于 2012-9-19 08:40:52 | 只看该作者
    巴山 发表于 2012-9-19 03:38 5 m2 J: X( J/ b* N/ o
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
    - E5 X3 Z" U. q
    : q- a% |/ p9 z- \ ...
    ( v/ `* e% C4 n/ R
    mongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的

    点评

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

    该用户从未签到

    12#
     楼主| 发表于 2012-9-19 08:44:52 | 只看该作者
    梦晓半生 发表于 2012-9-19 04:21 ; z% ?# E( U$ v
    谢谢。
    ) g* @- T( G  I# C# D% x! B1 C0 J4 `" }- t7 S; \. ]& F
    中文看得真累,大部分还是英文术语。

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

    [LV.1]炼气

    13#
    发表于 2012-9-19 14:16:01 | 只看该作者
    shengnan007 发表于 2012-9-18 12:44 1 ^( }8 H2 O( M- X# D  X
    是我啊。。。这都能被认出来。。。
    , v; @6 f" ^2 i6 g3 Z  \
    是邓嫂么?

    该用户从未签到

    14#
     楼主| 发表于 2012-9-19 14:17:53 | 只看该作者
    profer 发表于 2012-9-19 14:16
    6 }0 n' k) L- g/ ?- b/ R是邓嫂么?

    # q+ B. g7 y) Z* L+ R: J( g7 K/ Q是邓的小兵
  • 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 , B8 V4 @5 P% H5 \, N$ S
    现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...
    ' k; b, x; c( W! U: B% u
    太好了,期待中,希望都带上英文reference。
    ; C6 C; q8 B: b' E' A4 g- M. C+ z$ ]! h. }7 K* ]
    现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。, i- _! w" G  A1 x- l* I" \4 y

    ( W6 m- w( D# V) M2 F7 nhttp://en.wikipedia.org/wiki/NoSQL

    该用户从未签到

    17#
     楼主| 发表于 2012-9-20 08:53:41 | 只看该作者
    梦晓半生 发表于 2012-9-20 00:57 + ~% M0 z! ?5 d) A
    太好了,期待中,希望都带上英文reference。+ M# ?0 c  \6 Y: a4 d

    ) ?7 @. }& I4 i现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...

    + N$ ~% P* M. F- V$ O& |% ?4 K现在写的也很纠结,资料太少了,哈哈

    该用户从未签到

    18#
    发表于 2012-9-21 11:52:33 | 只看该作者
    shengnan007 发表于 2012-9-20 08:53 * o" X0 R( E0 z
    现在写的也很纠结,资料太少了,哈哈

    + F0 w; ]5 K! ?7 _8 Y/ t- l  F& g建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
    - ?3 V( C3 k% b2 N% O
    5 n* U! J5 G& g# o; {, N/ y! K/ ~http://en.wikipedia.org/wiki/NoSQL
    0 Z/ r% A: K7 Y! v# z+ z3 T  N, c) X7 Q3 n  D& B2 R
  • TA的每日心情
    郁闷
    2019-4-22 08:49
  • 签到天数: 38 天

    [LV.5]元婴

    19#
    发表于 2012-9-21 17:03:12 | 只看该作者
    恶魔吹笛来 发表于 2012-9-19 18:35
    & e* z$ i  C0 v- `9 ?8 D( c有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
    % u  `) ~% _, J, s$ K2 s- K5 F1 z
    有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。

    该用户从未签到

    20#
     楼主| 发表于 2012-9-24 09:11:03 | 只看该作者
    梦晓半生 发表于 2012-9-21 11:52 2 g! [% L' z! ~$ z- T
    建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
    % c& \# t) H% Q, r" r3 B- c# ]; y$ S2 |" F
    http://en.wikipedia.org/wiki/NoSQL

    4 V$ p/ z0 K# r1 B9 [& _1 A# D好的好的,现在这个写完,然后开始写nosql

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

    GMT+8, 2025-11-9 12:05 , Processed in 0.047821 second(s), 22 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

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