设为首页收藏本站

爱吱声

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

[信息技术] MongoDB架构概览

[复制链接]

该用户从未签到

跳转到指定楼层
楼主
发表于 2012-9-18 12:31:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。
" [5 d  J$ F9 D1 {- x& J
) |- v# Z# ]: O8 Q) d: E; L    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?
3 D8 ]9 x. B: B! g' Z
5 m) Z9 ?+ k$ S# K2 J    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。
8 ?1 z1 T7 \/ K  q- ^( O1 Y2 Y/ ]! h; N* L4 E9 h
& [% y. I1 _3 E5 U

3 u. l8 R/ u8 G/ R# {图1-1 MongoDB架构图

0 c) v' ]- v: Z# }% D8 C
/ p0 j' _# n, ~8 T7 t    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。; J, I3 p0 m! T9 a3 D$ m* k+ [5 _
1 b! {6 E  w8 a7 |
Shards9 h. y. e2 @" K2 y$ l

4 j1 s: C/ T; [  c    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。
- t2 w& q4 O3 ~1 a# A. `: s; c- e) R
- D1 z7 K2 m" y+ s: {+ A5 Q    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。3 l( ]7 C" o2 |" z- |' L

3 N1 G" ~- }( R' P7 ]7 g) |  n    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。. U* \, j. b9 ]1 u" r
3 l/ Y* I; |( z7 B& }0 G2 ?1 \
    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
# z! }1 o0 _; c) x  z, ^3 l6 j
* X# U, \* h, b1 UShard keys- W( d" o  x# G8 S' k4 F# _
        / S2 F6 p* D+ _9 H+ m" Z" I8 l: C
    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。
( M& i3 T3 S& C  O4 W* l4 Y1 G# Q
$ L" J6 p& p9 h3 C0 D- o+ w+ P) g    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,
& {% |* g- h2 Z2 n4 g( u9 g
3 b0 c  i) F# N1 h+ k& r% v4 a{
" n, f) n3 K+ E7 n, i  "ISBN": "987-30-3652-5130-82",
6 U. @) S9 o' u8 m5 `  "Type": "CD",
3 Z& k+ X3 O2 E* N5 ?) r. F) N  "Author": "Nirvana",( |" S% N6 k3 [7 L7 V: @# l# d
  "Title": "Nevermind",
% ?. G3 R: ]. w7 U* Q  "Genre": "Grunge",% W' X9 _/ Q# d$ x
   "Releasedate": "1991.09.24",
  {# [/ |: t/ K4 v& g- Z& q   "Tracklist": [
: W& J% H1 Y9 L     {9 U% t+ e- E) n
        "Track" : "1",
# ?9 L/ J7 b2 G2 m( d/ {- y# B5 E        "Title" : "Smells like teen spirit",, G4 ]  Y% S, o1 C
        "Length" : "5:02"
2 Q, d% U0 x3 X     },' J* ^# o, s- l
     {
( B8 y5 R6 ?5 \0 x9 V  ~        "Track" : "2",
- T2 x& D: V' Z+ |        "Title" : "In Bloom",! U$ Y3 @* W, G! B$ H' F7 d
        "Length" : "4:15"
5 T' L/ y- ~3 C# [: t9 }     }
0 r" U+ X5 }- H   ]9 L4 j8 c) Y* k
}
( W7 {, B' t9 U. P( h6 |. b: _8 s: q8 Z# Y/ V
{% t1 N% L- P3 G9 D) h
  "ISBN": "987-1-4302-3051-9",
5 n1 J3 r. P$ |0 t  "Type": "Book",
. @* D6 }6 u2 G9 t; m9 J7 w  "Title": "Definite Guide to MongoDB: The NoSQL Database",
$ A& |3 [3 Y6 Q: Q8 N/ ~# ?9 }  s  ]  "Publisher": "Apress",# C' @" ~/ ^/ N, k' V) t* z
  "Author": " Eelco Plugge",' k8 }' J( G& f8 s; z- N/ G' n
  "Releasedate": "2011.06.09"
- O( I' w0 w- P+ @4 q  J# P}* y+ W5 Y, N( w0 T1 \5 C

3 r+ t" ?* h6 ~1 s# G" W    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。
! K& p" E( n" [$ W) S
6 s" Z# c" c# W4 l    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。
4 g4 V! n6 j* E* E* Q: X  |" [9 J" N8 {+ K6 _6 t/ d# [+ R
    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。" y6 m8 r& Y. Y$ Z. N% q' ?0 v5 N
  q  M% h7 @' r( x3 c1 y
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。
" V" w  V% \1 E5 s, K* }  j6 C
1 o9 V8 q' W: g) b    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。/ {/ i4 m5 E0 }" t6 d7 |

. l& F5 ~" o; _7 N9 A, CChunks
0 ?! G7 G. W4 ]$ Z5 b, O  S        + C% z! r) s7 d/ S
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。. C) I0 f- B( X+ }4 u9 A  h
! H) l8 O$ H- I! t* k. N  c

+ f2 X, M1 E1 Z/ T, C" G图1-2 chunk的三元组
% ?& Q( J, b5 O2 h

! Z; g) `* ?" ^* w0 P    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。
) R$ B1 a. D, r) P1 `8 S
! J- a8 ~" Y" d) {% C    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。
4 M% V" A: _! W. W: f5 C8 \5 j$ J& l1 i: Q" q
    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。0 K- e3 ?/ Z; _9 Y' E
, E! Z3 G9 W: ~/ z) c+ l+ H
    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。& W* U( z6 z' w' Q# g) s6 X

& @  C/ @* A8 i. I8 \# ~* s    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。: |5 t! _1 w1 u- g( {  a$ k- B
% c& M( z8 b( S$ Z; \9 [& J
    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。  K5 T: A/ ^6 w3 T1 ]# w

% {( ]0 @) R% r/ w: }) kReplica set0 y/ i  i. m3 P5 E# ^, o, r
        
8 j6 Q* B/ v0 ]8 K9 j. k) v2 O6 n    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
) z: P' f* [5 w0 G2 A. T2 z9 G- ?
  c: B% ?( U/ R% [0 y+ m% D    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。
( A7 Y, M2 D; q& C
5 ?% x; Z  V9 [! C5 A0 i8 H    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。' F; Y6 r' h3 I: C3 W, `  z' [; \
4 h( k- {! }/ G1 i
    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。
: k, _/ M/ n; }2 D8 q+ \- I" h
) ^% E/ r! |* e8 E/ X  b5 Y4 @) VConfig Server
/ Z' ?3 f, p. O! ]- w        # Y6 g2 y) u1 f! W
    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。  r2 W0 }9 m5 i7 Z$ d
  c( I$ [5 H! e* H, H3 N
    每一个config server都包括了MongoDB中所有chunk的信息。0 B* _- {- U! ~5 Y4 C) L, M6 _( m

+ U  O  y" V5 S9 s$ R! y    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。
8 s" p. P6 D2 @* I* r
! Q0 \9 v1 R( q9 j1 q+ I  s/ Q    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。, h! c9 o7 L+ Z4 X0 P4 h
8 \: [0 K' D3 S1 X  p8 }6 f/ R8 m
    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。
3 A6 z, s8 }7 K) z+ w/ _) {/ p  A3 X" K& }$ B
Mongos2 P7 B* K5 c2 C9 Z$ E& J/ }2 Q* I. t: F
; q; h; W9 L/ b& M2 G3 y& L
    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。
! @6 d% P& S. k9 r# {: `
' q2 N- W: D$ F& e$ g' z    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。( C. T! b. M- D$ s2 [2 p
2 ?/ g0 |3 s+ l9 \7 h
    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。
* l& o9 W; |5 |1 j
9 b/ L# J2 o& k, f. M' C* l    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。, f: Z7 v( ?" c

9 z* g0 w- [( Q4 _8 a    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。
" v. z5 R0 C( Z0 ?
5 u  f! K8 y( n  a( W' ?& n9 ^9 C1 F% g% z, R* i8 i! T2 m
Reference,
) U& M+ Y9 l) P4 C+ E3 J' e$ v3 V; M/ o% n4 l- X: K
[0] Architectural Overview& u! \: _( I8 j' x8 ~) O' Z0 Y
http://www.mongodb.org/display/DOCS/Sharding+Introduction
+ x. B7 j) a6 r3 z0 `" d

评分

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

查看全部评分

该用户从未签到

沙发
发表于 2012-9-18 12:40:50 | 只看该作者
本帖最后由 PenPen 于 2012-9-18 12:44 编辑 . ^+ J7 [  y2 I) J9 N% M
9 z, D7 e8 y4 ^/ I9 O' `- T" ^

1 R3 A' k) D8 F1 p* [您是和邓侃一起写文章的盛楠么?

该用户从未签到

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

该用户从未签到

地板
 楼主| 发表于 2012-9-18 12:44:45 | 只看该作者
PenPen 发表于 2012-9-18 12:40 - C  H' ^! l1 z2 d( u6 K
您是和邓侃一起写文章的盛楠么?
/ T9 |: |8 k% [' `  q$ e: K
是我啊。。。这都能被认出来。。。

该用户从未签到

5#
发表于 2012-9-18 12:47:20 | 只看该作者
shengnan007 发表于 2012-9-18 12:44
) \0 _1 g6 s* M2 K# a  {0 E6 }是我啊。。。这都能被认出来。。。
. F; U' ]! J! D0 t+ f4 h
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

该用户从未签到

6#
 楼主| 发表于 2012-9-18 12:49:50 | 只看该作者
PenPen 发表于 2012-9-18 12:47   B$ k) g8 E' W, _+ I; B7 R7 h
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

1 O% p  ^" q0 w多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,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 ^/ p: K7 W$ ^/ r- n* s  w多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...

    3 j2 l2 z' H8 ^1 n9 I* x1 _; _欢迎,欢迎,已经给你变成正式会员了。

    该用户从未签到

    8#
     楼主| 发表于 2012-9-18 12:57:15 | 只看该作者
    不爱吱声 发表于 2012-9-18 12:51 - V2 Q+ |4 E6 P0 }9 o9 H
    欢迎,欢迎,已经给你变成正式会员了。

    . Y2 U1 t- s/ Z' j多谢多谢啦~~
  • TA的每日心情
    慵懒
    2020-1-15 02:37
  • 签到天数: 1287 天

    [LV.10]大乘

    9#
    发表于 2012-9-19 03:38:34 | 只看该作者
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。9 n: c( B0 Z' T  b
    ' d7 p9 v( o; S9 j. S9 {' Z3 k

    该用户从未签到

    10#
    发表于 2012-9-19 04:21:40 | 只看该作者
    谢谢。
    1 K' ~4 X7 v( y! m4 A3 \* k7 |3 `- j4 L/ n- Q* V' U
    中文看得真累,大部分还是英文术语。
    ) v4 S9 n% N8 W4 j/ c! Z1 O6 Q  P; z6 d; a6 W7 B. R7 l
    这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。3 c/ A8 K7 B8 ]/ j0 s3 p# z8 ~9 O
    3 F, A! i+ i" j/ Q1 k  @
    现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。

    该用户从未签到

    11#
     楼主| 发表于 2012-9-19 08:40:52 | 只看该作者
    巴山 发表于 2012-9-19 03:38 " V$ c; L- _9 S( ^# `. Y
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。2 ~+ p+ U+ Z2 B* ]0 q1 g0 j

    2 a9 _/ B8 B! C0 u2 e' M* l  K& r ...
    ; ], E+ L, ]2 Q, _& ~
    mongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的

    点评

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

    该用户从未签到

    12#
     楼主| 发表于 2012-9-19 08:44:52 | 只看该作者
    梦晓半生 发表于 2012-9-19 04:21
    5 e9 B2 g: u8 S- s7 F谢谢。% K' ^8 l/ u. ]$ W2 k6 g" Q
    7 ~( K. K) ~1 v! e+ l( m
    中文看得真累,大部分还是英文术语。

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

    [LV.1]炼气

    13#
    发表于 2012-9-19 14:16:01 | 只看该作者
    shengnan007 发表于 2012-9-18 12:44
    8 F9 |4 Q  |3 Q% r! r; J是我啊。。。这都能被认出来。。。

    9 s# O% e& K5 {$ ^  ]是邓嫂么?

    该用户从未签到

    14#
     楼主| 发表于 2012-9-19 14:17:53 | 只看该作者
    profer 发表于 2012-9-19 14:16
    $ E0 Y, }+ O$ [- t" w8 ?是邓嫂么?

    7 V1 y+ A1 F, s; h是邓的小兵
  • 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
    5 E: k5 h: ^, P; N4 R! O现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...
    1 w! D) h  t. M7 _) _( ~& k
    太好了,期待中,希望都带上英文reference。
    , M* E1 g" A  O. w6 u! q% n; F& Z1 ?  K7 m$ Y# c: J
    现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。
    ' _4 G  D' s" E$ @! I* f
    : r1 o$ L" v4 ]( e- g2 h* u/ d) fhttp://en.wikipedia.org/wiki/NoSQL

    该用户从未签到

    17#
     楼主| 发表于 2012-9-20 08:53:41 | 只看该作者
    梦晓半生 发表于 2012-9-20 00:57
    * r( H5 q$ P- Y9 z太好了,期待中,希望都带上英文reference。
    ( B- {$ l5 w2 w( Y0 u
    1 ]" h8 D; X' }% q现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...
    & O$ V' G3 h6 d
    现在写的也很纠结,资料太少了,哈哈

    该用户从未签到

    18#
    发表于 2012-9-21 11:52:33 | 只看该作者
    shengnan007 发表于 2012-9-20 08:53
    - a& u% p4 S. ?3 S" c, I  ~( a现在写的也很纠结,资料太少了,哈哈
    ' f& i, b& q# t' N; ]( Y' s* z/ _: W
    建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
    9 n: L* m  u) @2 {
    # B( i) I. w* T6 Zhttp://en.wikipedia.org/wiki/NoSQL2 s( P/ H7 q  D, B; o

    5 ~- r6 `% A5 N. ?
  • TA的每日心情
    郁闷
    2019-4-22 08:49
  • 签到天数: 38 天

    [LV.5]元婴

    19#
    发表于 2012-9-21 17:03:12 | 只看该作者
    恶魔吹笛来 发表于 2012-9-19 18:35
      z9 b, |# ]8 P/ _# T2 O0 k有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
    ' b; z1 R4 _# C/ l: S+ Z1 _$ A& a
    有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。

    该用户从未签到

    20#
     楼主| 发表于 2012-9-24 09:11:03 | 只看该作者
    梦晓半生 发表于 2012-9-21 11:52
    0 ?- r/ B' _0 [7 a建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
    ; G1 L$ T  k  h# S3 g: U
    0 C, m, g3 i. C0 g  Thttp://en.wikipedia.org/wiki/NoSQL
    " L0 A% G4 Q' I6 w8 v
    好的好的,现在这个写完,然后开始写nosql

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

    GMT+8, 2025-9-19 16:17 , Processed in 0.052777 second(s), 21 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

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