设为首页收藏本站

爱吱声

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

[信息技术] MongoDB架构概览

[复制链接]

该用户从未签到

跳转到指定楼层
楼主
发表于 2012-9-18 12:31:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。
& {7 v: V; q! Z  S: p/ [- M. I$ b9 D: D9 b- y  ]/ r! e3 r
    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?+ F7 n+ @% Z6 C; c  e

  N! R( }1 [1 p- s+ \. j0 H2 W    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。; [# w! h. B8 W# v9 b  @
3 x" K8 V' @: u7 y8 P

$ C+ }+ ^& u- R0 k8 [) w  R1 N9 ?; I# [
图1-1 MongoDB架构图

" b/ f6 O& P- ?2 d: |" r5 f' D) Y# O3 y
    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。9 N9 M! }+ }8 P+ j; C
# ?9 r7 J9 x/ m3 q% G
Shards( N7 t9 ~! ], J) u6 p$ c

' S0 q- {( v. M7 [' z0 W+ s! d& b    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。* [' {( Y' x2 c( ^2 Z: H

" M. q( W7 L  I: e/ p, F    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。/ p5 S  W% Y7 r; @
6 @" V/ w5 t: M) o
    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。
& b: i, C" h# @
* U( a/ d  O  J' I2 H# r' j    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
0 f/ E9 |; @: d/ @1 M1 n6 q; P" w( X7 M" ^2 v
Shard keys
9 X: d0 ?) }- b8 U  {! l9 R        
1 W! u1 ~2 ?; a" l0 H& u, C4 E2 H9 A% N    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。
" }, e- J8 @/ s; j" B3 t+ t$ i; H
( h; N% ]3 s3 ]6 r( p1 k  i4 X  l    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,) U% D0 `; R/ h/ ?6 X
* c4 I3 z" g$ h3 r- Z
{
, ]6 L$ n5 z8 r6 k. I  i  "ISBN": "987-30-3652-5130-82",
- P: Q1 `) C4 k; u' F  "Type": "CD",! _, b" Z# r* r8 E
  "Author": "Nirvana",: U4 p6 C5 n! H8 e: q" N
  "Title": "Nevermind",
- V+ W4 Q& S& r6 C4 G  "Genre": "Grunge",6 E$ J9 h9 [" B/ F, c
   "Releasedate": "1991.09.24",
) y8 `- i! |" K" h+ t4 _3 J! G   "Tracklist": [: c- D1 M2 A: N/ _
     {7 g: l2 X6 X$ g! \+ {: \  S  \8 P
        "Track" : "1",
. {4 u$ a! R8 V2 t) d        "Title" : "Smells like teen spirit",
7 D) I# X2 F. c$ r1 `  `        "Length" : "5:02"- J8 O6 H- w2 j+ J# b
     },  ?- Y. W) g; T4 H
     {- @6 f% H; `" W# W
        "Track" : "2",
, J  i( e! M+ V. s- |2 m        "Title" : "In Bloom",8 P# f3 ]- p' O
        "Length" : "4:15"( g; @$ _3 a  Z* w  m+ q8 A
     }
$ A1 t4 R( i1 n/ k   ]
5 d( n& q5 Z5 J* x8 u( m/ j% t# Z}; y$ K. o1 X4 M/ w5 X" @$ Q
; r4 c6 o+ \- u  H% R$ H
{  ~4 m; ~+ y, [" B& }! t' Z
  "ISBN": "987-1-4302-3051-9",
7 j; }9 J, c' b" n, y) q( s! s2 w  "Type": "Book",5 w4 T+ v4 c5 q: b! I. k1 F7 C
  "Title": "Definite Guide to MongoDB: The NoSQL Database",) `/ W6 W# P1 }! |" I9 v! X
  "Publisher": "Apress",
! m% U* p- y1 {+ ~% y! J( w  "Author": " Eelco Plugge",1 b, g9 p5 w6 B( d8 g2 Q$ c
  "Releasedate": "2011.06.09"
1 a9 A3 x' ?, T! ^8 |: |}& A, m# ^! {) N- ?# U& ~4 H
  B. X; X: l3 l( C; b2 x
    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。2 Y& m. D0 }; S$ T
" c! e5 O, z  b8 V2 W6 T4 ?: P1 c
    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。& \5 L! g5 q8 u/ ^
7 a# b; g% G2 r% q
    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。
( z- C  x+ r. e2 W+ U. f. L% k# F9 ?
$ ]1 j6 A+ X% `. G/ T7 a( W    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。! i/ y5 l6 i$ o- v
& T& A# j8 W! U+ h% a
    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。
% n0 v, B% X9 U5 g# t0 l( x+ m+ _) i' C7 c' T/ H& M' P' a& Z
Chunks
3 a, q# n2 Y4 S        0 f% G3 }) S' L0 h
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。
" ~( J: h! R* n+ T/ t% e+ I: h. }9 z! c4 ?. j

: l3 j) P; w) M( e* @图1-2 chunk的三元组
# _- D5 Y* o! ?  b# N4 k

( g1 X4 k# m3 ~$ C1 q4 I+ W" H2 \. y+ s    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。
9 Z7 L$ t. k# `3 t9 R5 r* y- x! L+ t: D5 o" W! G
    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。
8 X# W) G3 ~9 [% }# @
7 t  O: r$ M6 \4 D5 m* w, g- q6 K* T6 \    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。
1 u. M) v4 R, ]0 |
* I3 A$ k& m( x$ Z5 ~3 S/ y7 S    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。0 g8 p$ b' g  R8 b& o

' s3 K' r0 L, g3 h$ d. `    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。$ r; z1 R5 R5 \& `
, z) H& m/ \, H; Q$ `7 a; {
    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。
3 R1 H" B: q8 Q, d2 U8 i% R( q% H6 s6 H4 v8 s5 O
Replica set
  I5 o4 V. L" z# x- a6 ~+ g        / A6 w' y: w; g" B/ C- P
    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
$ ]% P+ a3 Z; o$ \! o# ~( w' V% q! e7 \
    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。# v5 o/ n$ Y2 `# e( s6 y

0 m- u5 N+ B2 O+ V3 n2 ^$ P7 l2 C    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。7 A6 [2 D- k: L2 ~5 x$ M2 _6 T

1 \9 R# N7 a6 t: Q    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。+ m* {3 b  m* W; N) Q
4 R! O1 b9 Q2 C7 K
Config Server& s5 |; z3 [+ a: `
        9 I1 @0 @& y) o
    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。
+ ~. ?7 S( P7 F8 w, S, ~& q* F! p+ s# h( r0 c  Q" M+ o
    每一个config server都包括了MongoDB中所有chunk的信息。4 H% [, f" D3 N. C
; c8 l- p+ e( b& U6 d. A4 m2 t
    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。
, L5 w1 I7 g# S8 n% t6 I$ w
0 y- l' W' _' ]% v7 q    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。
) A" t  ^, K# ]6 P: D7 F2 m
" L# D( t1 P8 m$ k$ f3 j8 R    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。* T. ?$ L* Q" F6 E* u' D5 O( J8 `& Q

' ~0 Q  v/ l- Y* L$ K: K/ QMongos/ I, X' v% _2 [( ^( G

: F' d% o; b) Q8 w2 n! X4 R, z+ Y    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。
" U! i* \; o8 T7 B5 Z) |4 t) o0 H
    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。
( J) T4 K% X5 g1 G( |* C6 L( x+ m. J: x
. J$ h1 L' u4 W2 ?" a    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。
' B" f7 j# e3 h+ f2 Z4 x3 }2 u$ R
. r/ N3 N8 j7 V    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。
6 T2 `9 N3 T, C( _- K! R6 q% ^
    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。: o: d( g% N3 }# h0 O1 K
: b, N8 k. d: r8 h- s. S. r% j1 y( T
% H1 S: L* I1 n5 H
Reference,7 s) _2 `- }0 ~) \6 j# g7 Z- F

( T. Q3 [; m; {: [. s[0] Architectural Overview
+ y( K+ S1 k( W( x  f; j3 Vhttp://www.mongodb.org/display/DOCS/Sharding+Introduction1 E# y1 h/ X/ y" c& }4 b2 y, r+ ^

评分

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

查看全部评分

该用户从未签到

沙发
发表于 2012-9-18 12:40:50 | 只看该作者
本帖最后由 PenPen 于 2012-9-18 12:44 编辑
. \1 a! h+ H9 D( w! e2 s- U: r/ ]7 i! @; D$ r& Y
3 h) V6 G- W; N; E
您是和邓侃一起写文章的盛楠么?

该用户从未签到

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

该用户从未签到

地板
 楼主| 发表于 2012-9-18 12:44:45 | 只看该作者
PenPen 发表于 2012-9-18 12:40
* w8 E% Z* u  ^/ i5 ~: q您是和邓侃一起写文章的盛楠么?
' G* f1 T- }; ?  B/ O
是我啊。。。这都能被认出来。。。

该用户从未签到

5#
发表于 2012-9-18 12:47:20 | 只看该作者
shengnan007 发表于 2012-9-18 12:44 ) r3 F# W$ T% _0 i5 c# c: l& y+ M1 A
是我啊。。。这都能被认出来。。。

) ^- @7 u2 a; w0 m9 `6 Q这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

该用户从未签到

6#
 楼主| 发表于 2012-9-18 12:49:50 | 只看该作者
PenPen 发表于 2012-9-18 12:47 , X/ ?7 S7 }  z5 h
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
5 u3 G3 C% p  K: _: x( m
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,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
    1 f! K; E* l, s7 w/ \8 F& E$ M多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...
    , Y: u& ]- D' K
    欢迎,欢迎,已经给你变成正式会员了。

    该用户从未签到

    8#
     楼主| 发表于 2012-9-18 12:57:15 | 只看该作者
    不爱吱声 发表于 2012-9-18 12:51
    ) p! k6 j$ X. w/ [# b欢迎,欢迎,已经给你变成正式会员了。

    ( y/ |; R; z- R. m0 B* V3 r多谢多谢啦~~
  • TA的每日心情
    慵懒
    2020-1-15 02:37
  • 签到天数: 1287 天

    [LV.10]大乘

    9#
    发表于 2012-9-19 03:38:34 | 只看该作者
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
    " _, X6 Z6 [  N- Y7 m# x* l
    & J- h+ N$ U/ _( ]' ]

    该用户从未签到

    10#
    发表于 2012-9-19 04:21:40 | 只看该作者
    谢谢。' b# l" H4 q* ?/ D9 W

    * G: s9 X+ X: T9 Y5 Q) w中文看得真累,大部分还是英文术语。  b6 H# [+ M$ u
    8 G3 X* e) U( G) ?1 t5 R
    这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。6 x) q# X3 K/ ]( {0 u
    * f- g7 w" W1 r$ V- W
    现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。

    该用户从未签到

    11#
     楼主| 发表于 2012-9-19 08:40:52 | 只看该作者
    巴山 发表于 2012-9-19 03:38 / l- K& Z3 \. ]9 Y7 t% v
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。0 K% l( }2 Y1 p2 y' j+ I5 g3 C
    ) v* x5 Q& A9 {/ ?; L, D
    ...
    ; u- M/ E0 F9 r3 @4 E2 m# G
    mongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的

    点评

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

    该用户从未签到

    12#
     楼主| 发表于 2012-9-19 08:44:52 | 只看该作者
    梦晓半生 发表于 2012-9-19 04:21 8 U4 R% K8 O5 A( \
    谢谢。
    ! V$ Y& L8 c1 j: l" u; N+ W4 G( V& B( h/ q- U& G
    中文看得真累,大部分还是英文术语。
    7 k" Z4 c& G5 _9 E6 X
    现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体系。这个系列文章的目的,是让大家了解mongoDB的基本的运行机理,这样以后使用的时候,可以知其所以然。但是由于这方面的资料很少,我也是到处找资料,写了这么几篇,再往后,就是边使用,边看源码,边写了。
  • TA的每日心情
    奋斗
    2018-1-6 00:24
  • 签到天数: 1 天

    [LV.1]炼气

    13#
    发表于 2012-9-19 14:16:01 | 只看该作者
    shengnan007 发表于 2012-9-18 12:44 6 k' q6 C& k" A8 C
    是我啊。。。这都能被认出来。。。

    / N& O$ E- u/ h+ B是邓嫂么?

    该用户从未签到

    14#
     楼主| 发表于 2012-9-19 14:17:53 | 只看该作者
    profer 发表于 2012-9-19 14:16
    1 ~2 d; s2 f- w2 o: l是邓嫂么?
    # Y- A) O* f; i) Y* W, f' g& U1 O. {
    是邓的小兵
  • 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 % Y, ~# E9 U0 w) D- W' b( l& ^' S% M
    现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...

    1 o3 r+ l7 K3 m! X% g3 a% t太好了,期待中,希望都带上英文reference。
    " K' c& ]& R; X3 L% l- g
    / x; j4 \. \& L- _) q3 {2 O现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。) u* B* g: w2 f

    ' x- V7 c+ p* G# N* ~6 jhttp://en.wikipedia.org/wiki/NoSQL

    该用户从未签到

    17#
     楼主| 发表于 2012-9-20 08:53:41 | 只看该作者
    梦晓半生 发表于 2012-9-20 00:57 1 a( N' E7 O% E" d2 q5 j# O' G
    太好了,期待中,希望都带上英文reference。
    8 J  m# l- t" @- z
    4 Z3 @& @) u) s/ B1 m& a现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...
    7 W! s7 ~& b0 K" a, T' a1 ^
    现在写的也很纠结,资料太少了,哈哈

    该用户从未签到

    18#
    发表于 2012-9-21 11:52:33 | 只看该作者
    shengnan007 发表于 2012-9-20 08:53 7 n! g! }* D+ k. Q
    现在写的也很纠结,资料太少了,哈哈
    ; K" I5 O( t! Q+ G% R7 w  ]& n
    建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
    . g. Z4 l, S4 U' p; F" }5 ?2 i" W  D2 I2 P+ o
    http://en.wikipedia.org/wiki/NoSQL* o; ]" G* [5 H2 J
    ; V! ]/ G5 T4 j. o8 H
  • TA的每日心情
    郁闷
    2019-4-22 08:49
  • 签到天数: 38 天

    [LV.5]元婴

    19#
    发表于 2012-9-21 17:03:12 | 只看该作者
    恶魔吹笛来 发表于 2012-9-19 18:35
    " H0 N* k$ `% k  Z2 b有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
    ) {, x" j* \+ c0 F6 G' c- c
    有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。

    该用户从未签到

    20#
     楼主| 发表于 2012-9-24 09:11:03 | 只看该作者
    梦晓半生 发表于 2012-9-21 11:52 ) @. _& R6 J( h5 e9 h/ b
    建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。3 w7 J4 \1 _' x3 M/ ?

    2 f. m9 y: v' P. O1 D# D0 thttp://en.wikipedia.org/wiki/NoSQL
    0 s% c' ~2 a! m
    好的好的,现在这个写完,然后开始写nosql

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

    GMT+8, 2025-9-8 08:54 , Processed in 0.048459 second(s), 21 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

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