设为首页收藏本站

爱吱声

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

[信息技术] MongoDB架构概览

[复制链接]

该用户从未签到

跳转到指定楼层
楼主
发表于 2012-9-18 12:31:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。
+ B/ o( E. F2 l) `1 I% U6 Z( g$ k; X* y
    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?! c% w5 m0 z6 ~" @6 {+ y
& j: s( Z# {. w! c" @$ K6 W( @' P+ m
    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。2 `# k7 Q$ U) ?9 R- {! R* S

2 s3 l9 T+ Z8 f& q8 m% I& V
) r- Z1 Y" U( T+ q7 q

% O/ F+ ^' A: Q4 r- I图1-1 MongoDB架构图
0 ]: J8 J& |7 d/ h: l6 ?  J8 ?

1 J! a0 k/ P1 a$ D/ H) I. R# ^$ d    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。- u0 P9 F- \4 p

. D% B8 ?: @% |Shards
) D3 J& ?# L% r, N* o% U5 i; ^7 h
, R4 Y/ e  F' }* g1 n9 o$ E# f    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。
" `# m) G* T2 j9 k2 Z% h/ E! u! F& r
    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。& L9 n7 n% C+ V8 u  z
, K4 V: o+ P- E1 P7 y2 i, M
    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。5 u8 |2 |6 [% [5 m6 g; p' @

/ u' z2 z& q4 e    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
  F4 Z% z( u. |8 G. j" @# Z
9 ~% F7 d, |* z' fShard keys# M0 i  |8 O" A- p3 b  Y, ~7 b
        & g" n9 y! S; `, X* }
    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。
; ^; W+ Z5 n9 o0 H9 {& F8 c4 U6 `/ @) b  n6 Z# G9 {3 A& C
    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,
! I' o( |9 U5 o+ F0 y, B* v! ~' u/ s) E
{
2 u0 l' ~9 m" ~: y( y  "ISBN": "987-30-3652-5130-82",/ B# T9 U# i- z% _% p
  "Type": "CD",* Y8 \, d/ J0 w0 K. U. B7 _$ r% {
  "Author": "Nirvana",
# o! H# x  R  q2 R7 G5 m  "Title": "Nevermind",
6 j4 N# ~/ |* Z  "Genre": "Grunge",
- p; \1 E+ d: l/ y$ R7 W2 `   "Releasedate": "1991.09.24",% b+ X9 p1 e0 o
   "Tracklist": [3 x' H$ q8 a6 G8 X& q, c! u  n  e9 p
     {
6 T# f  ~2 [9 c' }. `6 S        "Track" : "1",$ S% g  m) ]# H  g
        "Title" : "Smells like teen spirit",+ {' m) x" u; f4 B+ a* Q! z
        "Length" : "5:02"6 k6 T; s1 @+ p. H+ v$ A
     },( q9 d- }2 b0 n, \
     {
2 n+ k8 [( q# B; E( i        "Track" : "2",
8 C+ T$ }8 {% R* I0 s        "Title" : "In Bloom",
% n8 j! X/ i! f& ^; `        "Length" : "4:15"$ U, F% d6 V0 ?) U& c, }
     }
; H5 ^! t. C* h# c+ z* \   ]
: Q; I# c/ l, h. w' \}5 |! T' m) F- j6 D

0 h  t% O; G' h{
  n; V( \0 f2 c* T9 k  "ISBN": "987-1-4302-3051-9",1 N- s" Q3 B- f+ n
  "Type": "Book",
, M0 R" Y* q; q7 j% e1 n; H9 f  "Title": "Definite Guide to MongoDB: The NoSQL Database",
7 y+ b, o6 M$ d  v* \. B1 y  P! s  "Publisher": "Apress",
6 G3 C: [1 E  T2 m) x& |$ \" Y  "Author": " Eelco Plugge",
5 D4 v9 z+ }, b' @8 y$ q9 [  "Releasedate": "2011.06.09"
/ y7 f: z) f% l}
; C& S$ p" m1 W- r! a$ P, g  c, w" R! P- a: W2 s1 D. i, }
    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。3 T4 S1 t8 P1 s) ~' K) l& }
3 ?5 f$ z1 g/ S$ M) x
    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。8 S" n3 v0 I8 k# e/ T$ M

# A+ w/ b) h. h    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。
9 Z" h5 n! S! }; ?+ c" B9 U4 J+ s
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。$ c  B8 |( e2 j# `$ a
5 P# e& h8 W+ w$ h) k
    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。
4 _+ T3 f9 e/ _1 t3 m# o9 {" @, O/ M+ S, c6 v# }# }: w8 ?
Chunks6 g( z+ W! z& s" E/ z
        5 o+ f0 g' r9 A: g6 h7 `+ D* C
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。
7 e/ l7 s  A$ g: \  M# j( F: S2 D9 u5 W& ]: b

: S+ M' g5 j" R' |图1-2 chunk的三元组

8 `: G, |! ~% b3 w2 a
% W/ t' k# O" w  K    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。( s# B' v4 s/ |) j# B( o
7 u1 N0 N/ A- c5 H2 T
    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。
2 ]: f$ {' ]  g; a  W9 L$ I0 R7 _) |# r
% I! R; k1 [  k6 G( ?    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。
: u, r5 r, e' R& D. e' p
" ?/ n  ?' s; [+ w7 N5 e. }. q    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。6 X; X1 u% I2 H) t. s, A: @. t1 X

# y. T) \1 z5 @+ F# I6 x1 V: q0 ~    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。* \& N8 a) {. P. e( Y& ~7 q

' |% ?: d. y' k, L    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。
, v, \2 i* R5 |! a4 P$ N7 H1 O
, K# P8 ^/ f( g5 \Replica set
8 K- a$ y: r, b        
0 h* B) x$ i5 S4 {" e9 O, _    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
1 {% u8 [7 B( U% X. @4 S2 k- S& D( e# C, ^5 Z6 g
    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。
9 g/ z3 p5 W2 V4 G: Z' i0 `
! s  j2 j9 L1 \' ~9 S    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。
! }- _: N' M8 T2 p4 I  h
% w& k9 w, i0 d' U, g3 l) F4 o    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。$ |# M! t( G1 ]& a  f
2 R8 A9 @% K/ f- [' K7 B- O
Config Server
! R* v  A% {" ]9 t6 V) J        
7 Q- N7 B: p4 }9 [6 o- l& l    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。5 `( b8 Y* M4 Q6 V9 R! i( R2 g3 E
% r! X. Q! i1 Y3 }
    每一个config server都包括了MongoDB中所有chunk的信息。+ r+ _0 V' d+ f! l* ~% f3 I( k
/ J5 ]2 |5 m) d# ~
    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。
2 L5 w* d& f. }5 ~: ?# |, ^
4 @6 W1 b. Z3 w! F" H6 s( X2 z    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。
0 a  ]( S$ h. O$ }! q( [8 E" D# V
  s; S6 t4 K3 f. b    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。
) S* g. P1 D3 t# W/ O2 b
& Z9 G& ]9 \. c( T( {# p) HMongos' y& }7 X& {7 H; Y3 ~4 p
! L, m+ g: ]6 A! C+ Z
    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。
; h2 `, m( `( F  n2 \3 o+ H& q
" r3 e6 X3 Y( \, x# N    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。& [/ A" y+ C1 g

6 |/ |. ^" u3 Q* Y3 B    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。
* s3 u8 }6 A- G& N% q% \8 f
9 S& O4 R5 M- s. E& b8 V    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。
7 d3 F2 W- S  Z5 j; D0 @! |/ t/ F8 o
    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。# B- `" w% H' m5 n" S+ T
8 T3 ^2 k" X& K

( {* K& n% e' }; s  k0 CReference,6 q  x+ i; E3 V6 a, a- Q$ n

5 r" x! p* h+ B4 P1 m[0] Architectural Overview7 d" t4 u8 |& j
http://www.mongodb.org/display/DOCS/Sharding+Introduction
* u4 l/ y1 h) _1 E

评分

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

查看全部评分

该用户从未签到

沙发
发表于 2012-9-18 12:40:50 | 只看该作者
本帖最后由 PenPen 于 2012-9-18 12:44 编辑 3 b2 B2 R8 x& I4 g: M% V. ^
- R6 n1 G! j! z2 v  H8 c

  W" n6 q+ o: n% G+ S% l* |& G您是和邓侃一起写文章的盛楠么?

该用户从未签到

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

该用户从未签到

地板
 楼主| 发表于 2012-9-18 12:44:45 | 只看该作者
PenPen 发表于 2012-9-18 12:40
' k, z2 z! C, p4 p您是和邓侃一起写文章的盛楠么?

, ]7 k" p, q! D6 ~) }) t是我啊。。。这都能被认出来。。。

该用户从未签到

5#
发表于 2012-9-18 12:47:20 | 只看该作者
shengnan007 发表于 2012-9-18 12:44
# R) N9 s& O* f6 p: @3 r( e: i是我啊。。。这都能被认出来。。。

1 z3 [4 _* p  E5 |1 L这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

该用户从未签到

6#
 楼主| 发表于 2012-9-18 12:49:50 | 只看该作者
PenPen 发表于 2012-9-18 12:47 ) q5 e& h' s/ m, S, K+ C
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
+ F0 T6 h+ n3 s+ l( A# B" t
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,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
    8 @3 F8 F8 B8 N1 K" ~; `# G多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...

    # M0 v$ z  X" j0 O8 n9 V- e4 C; e欢迎,欢迎,已经给你变成正式会员了。

    该用户从未签到

    8#
     楼主| 发表于 2012-9-18 12:57:15 | 只看该作者
    不爱吱声 发表于 2012-9-18 12:51
    , _: J4 I  K! r0 e  |3 ?! t$ h欢迎,欢迎,已经给你变成正式会员了。

    + M5 N- a' t1 Q2 [  ~+ Y7 W多谢多谢啦~~
  • TA的每日心情
    慵懒
    2020-1-15 02:37
  • 签到天数: 1287 天

    [LV.10]大乘

    9#
    发表于 2012-9-19 03:38:34 | 只看该作者
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。0 A" c- `7 k4 R4 e
    1 O+ s' j, U) k0 s) m

    该用户从未签到

    10#
    发表于 2012-9-19 04:21:40 | 只看该作者
    谢谢。& L2 e: g7 v6 u9 x) O$ V, f

    ' o+ U4 O  N% W6 ^9 f# Z中文看得真累,大部分还是英文术语。" x/ w$ S( M' M. F( ~# N/ g
    : G% C# V7 V/ ^
    这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。
    0 Y- }6 s% X$ d- r/ _3 W+ W3 [& W" k* {7 J) y9 x0 q5 i1 a
    现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。

    该用户从未签到

    11#
     楼主| 发表于 2012-9-19 08:40:52 | 只看该作者
    巴山 发表于 2012-9-19 03:38 5 H) r# l( ?2 n
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。+ h, k# Q0 J$ s* O" A

    " H0 M$ d3 j0 B6 l2 W ...
      b4 h7 Q% k. f; i8 o$ ^, h! K
    mongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的

    点评

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

    该用户从未签到

    12#
     楼主| 发表于 2012-9-19 08:44:52 | 只看该作者
    梦晓半生 发表于 2012-9-19 04:21 3 ^# U$ Z( ?: m# C9 l
    谢谢。* c' v# c8 i' L
    % X$ h' N7 o+ p
    中文看得真累,大部分还是英文术语。

    * f9 N( }; N) 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 2 i( d0 `) ~( s# f. a! X
    是我啊。。。这都能被认出来。。。

    9 `7 U' w$ S6 k: ^是邓嫂么?

    该用户从未签到

    14#
     楼主| 发表于 2012-9-19 14:17:53 | 只看该作者
    profer 发表于 2012-9-19 14:16 2 Q# q9 Q* Z( ~2 j5 o0 W
    是邓嫂么?

      R3 W2 V% n% G6 ]9 K是邓的小兵
  • 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
    ) V& O4 v6 ^1 F现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...

    . Q1 S0 g) Q3 r) F* N$ Y太好了,期待中,希望都带上英文reference。" O  V1 G* N& F9 z7 l

    6 h' ~; M( ~4 a& y5 U1 H现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。; `2 O" t  Q- }" W

    $ a! G! w/ m' b2 r9 S' Mhttp://en.wikipedia.org/wiki/NoSQL

    该用户从未签到

    17#
     楼主| 发表于 2012-9-20 08:53:41 | 只看该作者
    梦晓半生 发表于 2012-9-20 00:57 0 u* H; h- n5 W
    太好了,期待中,希望都带上英文reference。2 D: r4 g/ a! @6 n/ r+ F" n5 H) v

    ' w6 s( g0 U4 x% r9 |6 `现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...

    / C; w. K) p& |* t% Y现在写的也很纠结,资料太少了,哈哈

    该用户从未签到

    18#
    发表于 2012-9-21 11:52:33 | 只看该作者
    shengnan007 发表于 2012-9-20 08:53
    0 D/ w1 e9 q/ A" O- t* ?0 l现在写的也很纠结,资料太少了,哈哈

    2 ~$ o! i. R7 u% y: d- C建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
    * m  t9 ], D8 E4 t2 A" K6 }; }1 V6 p0 o3 O% Z) R1 n
    http://en.wikipedia.org/wiki/NoSQL1 h( B. f+ ~3 l2 z5 M5 J& h

    5 {9 n; F' x; V
  • TA的每日心情
    郁闷
    2019-4-22 08:49
  • 签到天数: 38 天

    [LV.5]元婴

    19#
    发表于 2012-9-21 17:03:12 | 只看该作者
    恶魔吹笛来 发表于 2012-9-19 18:35
    $ e% ^: E) I" y有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
    9 m% q( I2 X0 l3 F) F9 y  B, d
    有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。

    该用户从未签到

    20#
     楼主| 发表于 2012-9-24 09:11:03 | 只看该作者
    梦晓半生 发表于 2012-9-21 11:52 ! X* h4 J; ^$ z, F- J5 j9 ?
    建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。5 W( U$ K0 q" O$ o& J

    8 z0 ~3 v9 k! g$ d* [http://en.wikipedia.org/wiki/NoSQL
    5 A1 E. j* u9 }# \6 s* T# e, X
    好的好的,现在这个写完,然后开始写nosql

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

    GMT+8, 2025-7-3 18:39 , Processed in 0.056545 second(s), 21 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

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