设为首页收藏本站

爱吱声

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

[信息技术] MongoDB架构概览

[复制链接]

该用户从未签到

跳转到指定楼层
楼主
发表于 2012-9-18 12:31:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。
6 K, s( W  }& }( W/ L+ [- z' P! |; e' C6 e. k
    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?
0 b" e0 U) Q, N' h: F( O
- q3 I" L) L5 l6 X: t: ?5 C) O    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。
" Q" W# H; u$ |" h# }: v3 ?
( p+ [7 _- }. X8 t& N5 v
* O2 M4 u+ x+ S  A; N

; T) {$ R' N( ^6 Y- s图1-1 MongoDB架构图
  @9 Z! x+ a, o8 e  B
2 y; q, J/ B. _; C
    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。7 ]' d. J" |) B8 |

7 U  e- r. ?/ _( Y' X. x) ~; UShards* v8 b% G8 ^1 ]% z7 N! a, L3 J% T

. Q" r" _* ~$ u' f    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。
8 p; M1 n, u' G% Y/ B$ k: F" N* x, |) O6 `* k/ A
    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。" b: S% K  O3 G- x

, a5 |+ E; A, H' O    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。+ _1 J' ?$ U* h

: }0 F5 ~" l, i8 P; A    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。2 m* @9 T  ?) K" p
1 E# e+ P& P5 J+ E
Shard keys8 |% S2 L3 p& K# \
        
) F* L7 A3 I# q* q3 m    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。
9 |' N# t# J7 ~: f+ s3 B1 J
7 ^9 D; ?8 X$ M/ Q    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,
  h2 _* W$ D+ y3 l- ]% i0 D" i: S
; J! M6 I0 _8 h6 |8 C/ L{
! g- S6 }. f' ~  W1 @8 \, m  "ISBN": "987-30-3652-5130-82",* O$ `  ?/ S$ L! Y
  "Type": "CD",
2 `, u7 w  }* _+ V  "Author": "Nirvana",& [  p) T0 _3 x, `
  "Title": "Nevermind",
2 `+ o9 c- |& T& W, F/ n* e  "Genre": "Grunge",1 P1 B( i( a/ ~+ O7 w
   "Releasedate": "1991.09.24",' a1 r' i, h% L8 k' ?) }
   "Tracklist": [
# R* K1 t, Q$ F  K     {- j- n' {1 ?" O& a9 {+ i
        "Track" : "1",
0 U; H6 I: U9 J/ I; u" m        "Title" : "Smells like teen spirit",
& e4 Z" M0 X6 p; {        "Length" : "5:02". j1 Y' o1 t& i# a/ u
     },
/ P& p2 O1 Q% _3 Z1 J3 T0 U6 ~     {- A7 w/ R; v% o* ~; c9 K
        "Track" : "2",
; {- \) {( t' r1 K        "Title" : "In Bloom",. U9 P9 ]2 T8 U
        "Length" : "4:15", D% r% j9 W; u1 P0 O, N
     }
* d( R) b, Q- @' F   ]
$ r- f" O$ \/ D& h}8 J/ C: M6 t' i5 Q4 v* l
9 a5 s% c( S3 t# \
{
8 l% D8 T5 C2 I  "ISBN": "987-1-4302-3051-9",
$ _$ Y- n6 @3 Q( P  "Type": "Book",; w! c& U1 T5 w( R. f, a8 q: h! Y
  "Title": "Definite Guide to MongoDB: The NoSQL Database",
6 h  d# G# m5 I  "Publisher": "Apress",5 K8 X* d# `) j( ]5 r+ r- m+ R3 N
  "Author": " Eelco Plugge",2 c+ U. K% H: x( g1 e& e  X
  "Releasedate": "2011.06.09"
" M( \8 x* B4 w  F; K}9 c! ~3 Z  u! V. ?: o$ o
' D5 ~8 q& z) H$ S! H# z; ?$ `6 H
    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。
8 H- T; h& {" w% B
% y2 B0 T7 d4 w' ~  p# d    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。
5 ?0 H- l* A$ V! R
+ W+ h0 O- ^2 Z' g    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。
. z; m* E/ [( ?/ r. M* R( ~" l  v& C+ y; O* M$ a* s5 e7 R
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。
5 F3 y5 P  F/ w4 x3 t( d2 D* d7 G/ t5 ^+ t0 H. G/ g
    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。
& s5 Z2 ]2 S' D* ~& [5 }6 f& ~9 u+ K
1 D( H5 j7 O' V2 f& C9 N0 ]: t) A1 GChunks  o) h1 o+ m0 ~1 Y1 Z; s: Y3 O% z
        
( x  q& `) O5 N" w& @    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。3 J& }* g6 N, \3 a% a* y" b- p" r) g) V
9 i& o& @9 z$ e6 d; I4 `1 Y
  u& ^' B6 ?+ d' P
图1-2 chunk的三元组

) g- @0 b7 W, D+ v* C" L6 C: T. N; r. S1 X- d! b7 g
    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。: p$ a. l. x/ h

( j0 b/ B5 b: ?+ u9 l; [' l    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。
/ D7 M  g' K( ?, q1 f
1 m, w' a# ?) g# w) y/ D    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。5 y% |+ A0 |( K) m: v# {6 d
7 m+ w" h. {& W+ A8 O. i6 i9 Y
    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。7 l9 t2 L0 Z9 K5 B" x
4 {; F" ^7 b7 ~) B% i7 h# ~
    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。! N5 x' ]/ h& S) O- _% F/ P
6 ~; L9 n$ c4 Z' n
    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。, D9 z5 B& j; ^! Q4 }, E8 n# {

/ e. S4 S) @( C* k0 w% v! {Replica set5 M1 F8 {- `9 }& v7 g. \( L+ Z; c% ]2 H
        
) D4 e5 m( f5 |5 e    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
4 |9 ~6 N0 z( r: W" r! \& `
4 p% N3 t' E0 x" l  ^0 P  O    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。
: j: F$ d% a7 R; F( U+ e3 K; g) q- m! U9 B# o0 ~+ {
    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。! e4 z7 Y. N5 _2 @6 `% h  O0 K
9 w+ f9 E( t  ?5 x# |2 W
    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。
. U; w7 f; f2 ?/ I4 C8 d
% e: [4 l% _8 `1 ^# j1 dConfig Server
& }2 [2 n0 Y0 z" A  o# n/ I7 s- `        
* u# w" z( q& d1 {- r& U+ e    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。' }$ T7 X2 U# c6 p5 }
) W. s3 J" p4 \- L9 A
    每一个config server都包括了MongoDB中所有chunk的信息。
* c/ |( g. K0 _
7 W+ V9 e  ~' \: x    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。
, b* F3 @$ R: L5 R* W
' K# Q- a/ q5 y: ~8 y6 B    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。& C( G# u; c8 g. i
- x, R/ I" z, c1 l5 h( [
    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。( W  T4 u  l. q
/ }8 N) {- x( A# F# I0 j/ `) {' X
Mongos7 n# o+ E8 x3 [* G+ ^3 _

/ Z8 b& {5 J$ ?/ y8 ?. Q( Z  y6 t    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。
" M' e8 d+ K" y" G* C% I  O( M+ P  m5 T' e  ~, a2 g* B& G
    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。: _% E! d+ T, B+ k
; I* r& O: k: N2 j. f
    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。
. k1 _0 T1 I, Z: u0 j+ S6 ^
4 C% f3 U4 r, N3 \# G4 c% `    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。
( h  u+ H7 Q, G6 I, G8 [3 e* g* [2 y* _6 `
    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。
6 {2 O4 I  S2 Y5 _) v) F( i( U0 C5 C4 r5 o" Q0 G3 y  T- f: N

% y6 w1 z, J4 |" e! Y! [2 F+ ~Reference,3 L9 v3 \2 g; W, d1 g8 ^
5 X' Z1 b% y2 e
[0] Architectural Overview* f9 N& U% o/ q) T% T
http://www.mongodb.org/display/DOCS/Sharding+Introduction
1 }2 V, K7 g7 F& D5 b

评分

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

查看全部评分

该用户从未签到

沙发
发表于 2012-9-18 12:40:50 | 只看该作者
本帖最后由 PenPen 于 2012-9-18 12:44 编辑 ) x& h/ \* L" N0 w
" Z% k3 A- p, i: N" _  C, `
  N* Z) t# o1 f" O
您是和邓侃一起写文章的盛楠么?

该用户从未签到

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

该用户从未签到

地板
 楼主| 发表于 2012-9-18 12:44:45 | 只看该作者
PenPen 发表于 2012-9-18 12:40
& d3 U1 O+ U. W! X: ?5 T您是和邓侃一起写文章的盛楠么?
# C  H& U  E. X; G4 {4 K
是我啊。。。这都能被认出来。。。

该用户从未签到

5#
发表于 2012-9-18 12:47:20 | 只看该作者
shengnan007 发表于 2012-9-18 12:44 9 r/ D# ~/ y/ ?6 C* Q
是我啊。。。这都能被认出来。。。
9 U, K& y7 E0 }# K% N' W6 X! J, N: k
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

该用户从未签到

6#
 楼主| 发表于 2012-9-18 12:49:50 | 只看该作者
PenPen 发表于 2012-9-18 12:47 1 G# z  x/ ]* S0 q! H
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~

+ K$ G$ N( p3 w' g3 S3 ?) z7 f多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,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 / [6 |/ z: w- w  E" L. D
    多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...

    ! M5 Q9 W% B9 o' F+ i欢迎,欢迎,已经给你变成正式会员了。

    该用户从未签到

    8#
     楼主| 发表于 2012-9-18 12:57:15 | 只看该作者
    不爱吱声 发表于 2012-9-18 12:51 4 z+ ]% I; s( _+ ~: }) b$ M
    欢迎,欢迎,已经给你变成正式会员了。

    4 v$ X6 k( R. {/ a# i多谢多谢啦~~
  • TA的每日心情
    慵懒
    2020-1-15 02:37
  • 签到天数: 1287 天

    [LV.10]大乘

    9#
    发表于 2012-9-19 03:38:34 | 只看该作者
    我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
    8 V# z) h9 [8 {% ]3 D$ [1 B7 z5 v; s* s) }" L' T5 V  x

    该用户从未签到

    10#
    发表于 2012-9-19 04:21:40 | 只看该作者
    谢谢。
    2 i# F# b9 N# p) r, g- ~
    * {0 k9 f% j) M+ Q% e中文看得真累,大部分还是英文术语。  r# u& F* @. s( z# Q* N+ d% B

    8 D4 @3 T! }  {这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。0 O+ \7 R9 b, d# Y0 p( P+ l* T+ ~( o; ?

    8 C; s  Y- a( U* _1 f6 O现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。

    该用户从未签到

    11#
     楼主| 发表于 2012-9-19 08:40:52 | 只看该作者
    巴山 发表于 2012-9-19 03:38
    4 F0 H: l2 a  Y, ?$ c我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
    / y8 F) D# |& }, _6 G6 I  K% C+ x  V- S3 z# L3 A2 l
    ...
    ; I" ]" l2 ~5 F6 g
    mongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的

    点评

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

    该用户从未签到

    12#
     楼主| 发表于 2012-9-19 08:44:52 | 只看该作者
    梦晓半生 发表于 2012-9-19 04:21 ) v' H0 `. O; ]6 n
    谢谢。
    , I! c, @: M! q! }
    - p( B0 }! J* g* r; t中文看得真累,大部分还是英文术语。

    , k# n4 o  P$ Z  y4 O! ]& c现在关于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 i" d/ ~$ r" V2 |
    是我啊。。。这都能被认出来。。。

    5 U2 {( U7 P$ U0 C是邓嫂么?

    该用户从未签到

    14#
     楼主| 发表于 2012-9-19 14:17:53 | 只看该作者
    profer 发表于 2012-9-19 14:16
    0 V! q6 Y! Z. H* V; s7 D是邓嫂么?

    $ q8 m0 x& S7 j; D! X是邓的小兵
  • 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
    ' L/ m9 x6 d8 h8 U现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...

    0 F8 S( }; E& {; e太好了,期待中,希望都带上英文reference。3 p: U3 u, c' [" s5 D

    . C5 F9 e! C& n  o2 r, g现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。
    . f+ }4 H* x2 |; @+ c7 T
    + n) m$ o: [0 s, i0 b! n0 chttp://en.wikipedia.org/wiki/NoSQL

    该用户从未签到

    17#
     楼主| 发表于 2012-9-20 08:53:41 | 只看该作者
    梦晓半生 发表于 2012-9-20 00:57 $ h7 {! j$ s- ]9 }, M( x  y& Y+ K  T
    太好了,期待中,希望都带上英文reference。  w! ?6 E' j1 _* `0 p
    / y5 B; q7 G1 I$ K+ _$ a
    现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...
    5 j* [5 B: F* I5 U/ v) y/ u) d& f
    现在写的也很纠结,资料太少了,哈哈

    该用户从未签到

    18#
    发表于 2012-9-21 11:52:33 | 只看该作者
    shengnan007 发表于 2012-9-20 08:53
    9 _0 N/ S: T6 R9 C现在写的也很纠结,资料太少了,哈哈
    8 ~+ o0 W6 Z& F9 w6 z. d: B* t
    建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。; m7 L5 k8 J/ z& S" a; n4 {

      q) s) b! c$ X$ qhttp://en.wikipedia.org/wiki/NoSQL% D, F( R4 q% a, l) n+ c

    7 G8 S% G+ n7 o2 \
  • TA的每日心情
    郁闷
    2019-4-22 08:49
  • 签到天数: 38 天

    [LV.5]元婴

    19#
    发表于 2012-9-21 17:03:12 | 只看该作者
    恶魔吹笛来 发表于 2012-9-19 18:35 % _* F9 E! V! ^0 P3 H, k& U
    有点惊讶 居然在这里看到这篇文章 呵呵 静待大作

    5 G* `4 b3 m1 q% f' M6 }有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。

    该用户从未签到

    20#
     楼主| 发表于 2012-9-24 09:11:03 | 只看该作者
    梦晓半生 发表于 2012-9-21 11:52 0 s3 D) Q; I' }. c% X* q
    建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。5 Z2 p, Y2 H' Q- k8 [) W! |! u" w1 h
    - ]8 V& ?: g7 I1 @$ u8 }
    http://en.wikipedia.org/wiki/NoSQL

    ! J7 r; y; g) G" R. a, S好的好的,现在这个写完,然后开始写nosql

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

    GMT+8, 2026-3-7 16:36 , Processed in 0.088989 second(s), 22 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

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