爱吱声

标题: MongoDB架构概览 [打印本页]

作者: shengnan007    时间: 2012-9-18 12:31
标题: MongoDB架构概览
    关于MongoDB,我们能看到的资料,基本都是在指导大家如何使用MongoDB,但是,MongoDB内部是如何运作的,资料不是很多。' ?% S* _& l( Y9 E

8 A3 X" i$ B) i$ {; |    阅读使用手册,会有很多疑惑之处。例如,有人说,MongoDB 等同于分布式的 MySQL。它把一个Table ,按 row,分割成多个Shards,分别存放在不同的 Servers 上。这种说法是否正确?8 G* C, w$ t) r# f+ v+ o# ~
7 d2 o3 e; U& j7 O) m  N
    不深入了解 MongoDB 的内部结构,就无法透彻地回答类似问题。这个系列文章,就来和大家探讨MongoDB的内部的工作方式。
& P; L+ Y6 W" J" h6 w$ |! b- ?4 p
9 g6 }- i% w. H3 L
5 [& m, O# H+ u# H0 V3 i: m
7 Z. s, z" X/ o5 l- N( p
图1-1 MongoDB架构图
$ v& _8 g8 a* C( s; _

) a) T. n% C% A6 F* I2 B# L    MongoDB 通常运行在一个服务器集群上,而不是一个单机。图1-1,描述了一个MongoDB集群的基本组成部分,包括若干shards,至少一个config server,至少一个routing servers(又称 mongos)。4 b  p9 r0 O1 x$ p* |
" D; w) w/ q& E! o4 c
Shards
6 V, Q' C, e" h6 B! c+ X1 k0 b; k9 u" ]5 X- H$ R; V& W
    MongoDB的最基本的数据单元,叫document,类似于关系式数据库中的行 row。一系列documents,组成了一个collection,相当于关系式数据库中的table。当一个 collection 数据量太大时,可以把该collection按documents切分,分成多个数据块,每个数据块叫做一个chunk,多个chunks聚集在一起,组成了一个shard。
7 E0 R# F- L4 g1 |) b/ v) j9 X- s7 a+ l0 o* t
    Sharding 的意义,不仅保障了数据库的扩容(scalability),同时也保障了系统的负载均衡(load balance)。
. q- F0 ^5 w5 j$ H( D& a. q) q" w$ n! W2 l0 T( ^6 `
    每一个shard存储在一个物理服务器(server)上。Server上运行着mongod进程,通过这个进程,对shard中的数据进行操作,主要是增删改查。$ ?4 V/ X! A" a, n& D$ {% d
, [4 X6 N( z& l0 X! K, ?' D, H
    如果系统中的每个shard,只存储了一份数据,没有备份,那么当这个shard所在的server挂了,数据就丢失了。在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
6 ?! f6 V$ N6 A" C6 k' ]  }, n4 Y; F
Shard keys
  K) x# m! K- h+ g8 V0 y$ M        ) v, Q: J1 Y9 Q
    为了把collection切分成不同的chunks,从而存放到不同的shards中,我们需要制定一个切分的方式。
8 X" y% t5 X: H3 j, R3 K7 i( s- B" z. T* V- U# g8 H; s
    如前所述,在 MongoDB 数据库中,一个表collection由多个行 documents 组成,而每个 document,有多个属性 fields。同一个 collection 中的不同的 documents,可能会有不同的 fields。例如,有个 collection 叫 Media,包含两条 documents,0 B+ y) |' [5 m. A

* M! z0 t& x/ o7 p{5 {. T' u  u; f4 N2 g% U
  "ISBN": "987-30-3652-5130-82",* {5 X2 {5 k/ ^4 z
  "Type": "CD",
' i! y& w1 M, `& D  "Author": "Nirvana",
6 b  L. E' V3 f% k  "Title": "Nevermind",
" I0 @) t: f/ c1 X5 G7 [' H  "Genre": "Grunge",! M2 I& r8 b& D3 x  p8 [4 v
   "Releasedate": "1991.09.24",( J% e; o) H; b- P, @8 Q9 [9 Y5 `; k
   "Tracklist": [
. x: e( ?, O5 h0 y$ \' F4 N+ q2 a     {' M" x  R8 a$ F7 t
        "Track" : "1",
! L* Z3 u5 z2 r9 F" B. E$ }6 y; x+ s        "Title" : "Smells like teen spirit",
5 ?7 |4 @/ E7 r        "Length" : "5:02"  }8 z" r; U+ @/ b# _* x
     },
) x/ _3 \) ^# d5 T, M9 x     {
( G! @& k, C* [! b$ D* Y        "Track" : "2",  C2 R- w4 y, c& C
        "Title" : "In Bloom",# g' r0 U5 S( p2 |$ m+ c3 H/ F
        "Length" : "4:15"
% W6 N0 o" ]4 t% p6 F; ^- y9 }( z     }: t/ g& |4 d5 v/ T3 R
   ]
- ^, `+ j9 `  v; ^! m  _( v}# ^! O3 Q" Y9 q. c9 g7 `( B

6 k' ?: y/ K) O8 m/ g$ X& Q{
/ w8 }2 |. [1 J  "ISBN": "987-1-4302-3051-9",
% z$ F  g" J, S: r/ `  "Type": "Book",3 g9 P. |; Q: z0 X& K
  "Title": "Definite Guide to MongoDB: The NoSQL Database",# p0 T2 f+ X0 a( v. |. [
  "Publisher": "Apress",
: i4 c  A4 s& a& }. L1 h6 ^  "Author": " Eelco Plugge",  q2 \4 a/ ~" Z/ K
  "Releasedate": "2011.06.09"
. C9 w) p$ b' I% D}
7 i" Q" d2 C6 g$ R5 C+ M8 P
  S/ i8 W3 O) _) x/ z8 g" U- {. j    假如,在同一个 collection 中的所有 document,都包含某个共同的 field,例如前例中的“ISBN”,那么我们就可以按照这个 field 的值,来分割 collection。这个 field 的值,又称为 shard key。# t( G" S( z3 H/ n7 G1 }
/ P# n8 c) h, o- h1 b$ m0 Q3 L
    在选择shard key的时候,一定要确保这个key能够把collection均匀地切分成很多chunks。) {+ j7 b5 d) K+ ?
9 C& V+ ?1 ?3 z6 U+ a8 z* m
    例如,如果我们选择“author”作为shard key,如果有大量的作者是重名的,那么就会有大量的数据聚集在同一个chunk中。当然,假设很少有作者同名同姓,那么“author”也可以作为一个shard key。换句话说,shard key 的选择,与使用场景密切相关。
/ |+ u" h. Y7 m& V6 B) H1 t' K  a  B! R( U
    很多情况下,无论选择哪一个单一的 field 作为shard key,都无法均匀分割 collection。在这种情况下,我们可以考虑,用多个 fields,构成一个复合的shard key。1 g) [+ f' N8 D* }
+ S4 [  g1 Q; J- `5 t  W& m3 f
    延续前例,假如有很多作者同名同姓,他们都叫“王二”。用 author 作为 shard key,显然无法均匀切割 collection。这时我们可以加上release-date,组成name-date的复合 shard key,例如“王二 2011”。
0 {5 A6 X% r* R0 T# k% V5 t' w/ F, {8 ~3 L9 s3 C
Chunks
# |3 g2 s& s9 v' ?9 {9 Z        ) A! g$ v% N2 k' {. ~
    MongoDB按 shard key,把 collection切割成若干 chunks。每个 chunk 的数据结构,是一个三元组,{collection,minKey,maxKey},如图1-2 所示。% @* g5 Z# ~4 q0 I; E/ N# j" j

' v* O$ m8 b. Q2 G/ _% y  z6 o
! P, n4 |; e+ g; @
图1-2 chunk的三元组

) I: r- Z5 \$ D  X* N: d
- \! l1 b! d9 o4 ?* w8 H    其中,collection 是数据库中某一个表的名称,而 minKey 和 maxKey 是 shard key的范围。每一个 document 的shard key 的值,决定了这条document应该存放在哪个chunk中。) T9 j& `; N' m1 W0 c/ l/ e# |
7 A( U! {; R7 o* M0 K  ^
    如果两条 documents 的 shard keys 的值很接近,这两条 documents 很可能被存放在同一个 chunk 中。
$ v5 h" G/ T& w
6 `) ^) l; o3 ]2 ~6 g    Shard key 的值的顺序,决定了 document 存放的 chunk。在 MongoDB 的文献中,这种切割 collection 的方式,称为order-preserving。, K( U& ?9 \# i
& l) M/ t, \  R! S4 ~6 C: q: g
    一个 chunk最多能够存储64MB的数据。 当某个chunk存储的 documents包含的数据量,接近这个阈值时,一个chunk会被切分成两个新的chunks。
; W& M7 I+ Y! N  t- u
9 P4 J. t$ E0 m: d& W( v    当一个shard存储了过多的chunks,这个shard中的某些chunks会被迁移到其它 shard中。- C: O" s* D, C! l/ w" \+ ^( [

- c. W& n4 F. y    这里有个问题,假如某一条 document 包含的数据量很大,超过 64MB,一个 chunk 存放不下,怎么办?在后续章节介绍 GridFS 时,我们会详细讨论。
) P* f; J8 ?$ a* G. r, d' X2 _7 u: p4 ^, [6 x1 @! F
Replica set
+ }' e& n; P3 |) I; p: L        - A9 p4 ?/ V; W# k: Z/ B: i6 h1 A& f
    在生产环境中,为了保证数据不丢失,为了提高系统的可用性(availability),每一个shard被存储多份,每个备份所在的servers,组成了一个replica set。
  p1 |& ^; G' m+ _# C. a1 ?0 |2 t+ C5 V. r4 J; u; z
    这个replica set包括一个primary DB和多个secondary DBs。为了数据的一致性,所有的修改(insert / update / deletes) 请求都交给primary处理。处理结束之后,再异步地备份到其他secondary中。: Q6 ~7 r1 D( Y! y- M+ b# H% L
% U! ?' e1 h  |$ E
    Primary DB由replica set中的所有servers,共同选举产生。当这个primaryDB server出错的时候,可以从replica set中重新选举一个新的primaryDB,从而避免了单点故障。/ G5 h, |" c7 H. F- A

8 |+ T  S, @4 |# C6 F- D$ M    Replica set的选举策略和数据同步机制,确保了系统的数据的一致性。后文详述。0 ?8 k( a2 v  I
% f$ d' x& P; K5 ~9 F) i* I  q6 l
Config Server
  E% h$ Q0 V: v" {5 b        - m4 y: }8 F' g$ j
    Config servers用于存储MongoDB集群的元数据 metadata,这些元数据包括如下两个部分,每一个shard server包括哪些chunks,每个chunk存储了哪些 collections 的哪些 documents。
/ e  W3 C8 V9 |. y% r2 y- q8 d) O$ C3 X8 q7 u" V  L2 H
    每一个config server都包括了MongoDB中所有chunk的信息。7 e8 j0 T4 A+ |9 |2 J& [1 ]' t

8 _. s1 X" c) i' k$ g: A    Config server也需要 replication。但是有趣的是,config server 采用了自己独特的replication模式,而没有沿用 replica set。. I( Z0 i9 p7 ?' F  _; I9 J
6 S' C7 J0 Y$ I9 X% W
    如果任何一台config server挂了,整个 config server 集群中,其它 config server变成只读状态。这样做的原因,是避免在系统不稳定的情况下,冒然对元数据做任何改动,导致在不同的 config servers 中,出现元数据不一致的情况。
  F7 {, G1 Z) {7 P, [- f- Q% d8 |7 N* d3 Q
    MongoDB的官方文档建议,配置3个config servers比较合适,既提供了足够的安全性,又避免了更多的config servers实例之间的数据同步,引起的元数据不一致的麻烦。( o( N' m" D2 t
+ i, L2 K. n2 q6 x* K$ z
Mongos
1 @8 B# e& n1 `$ D  u# s: n$ G3 |5 c0 E5 E
    用户使用MongoDB 时,用户的操作请求,全部由mongos来转发。
' t/ Z* }; B; H- G- Y
1 |' A: w: h3 T6 b* i; Y% u2 S    当 mongos 接收到用户请求时,它先查询 config server,找到存放相应数据的shard servers。然后把用户请求,转发到这些 shard servers。当这些 shard servers完成操作后,它们把结果分别返回给 mongos。而当 mongos 汇总了所有的结果后,它把结果返回给用户。
4 E; I! z7 d. W" R% T1 I
" v* x2 |! A7 i    Mongos每次启动的时候,都要到config servers中读取元数据,并缓存在本地。每当 config server中的元数据有改动,它都会通知所有的mongos。
/ w  P1 ~5 i7 l  P) J# a( i- p: |! s- I) N
    Mongos之间,不存在彼此协同工作的问题。因此,MongoDB所需要配置的mongos server的数量,没有限制。' s) N9 R( L# S3 D- j  M
" l1 n; A$ ~" f+ m9 ]
    通过以上的介绍,我们对每个组成部分都有了基本的了解,但是涉及到工作的细节,我们尚有诸多疑问,例如,一个chunk的数据太大,如何切分?一个shard数据太多,如何迁移?在replica set中,如何选择primary?server挂了,怎么进行故障恢复?接下来的章节,我们逐个回答这些问题。/ [. w; i  w" |- H/ Q5 X
$ }* ^# S1 R4 f, |5 C* Y" a
# l3 j2 }: ]( F- l8 U* \. s# H
Reference,5 c2 X' ~0 t4 j/ X
4 a% o" W1 c' q$ f$ U" ?
[0] Architectural Overview
1 v& u4 S5 `/ _6 Y+ C: t$ xhttp://www.mongodb.org/display/DOCS/Sharding+Introduction" S" e( M# C& [: I; j

作者: PenPen    时间: 2012-9-18 12:40
本帖最后由 PenPen 于 2012-9-18 12:44 编辑 9 F. B5 ^& U: n. x: c8 D

3 A5 f! |. p9 B/ L$ z* ^' o" l# r' q# P8 E, R
您是和邓侃一起写文章的盛楠么?
作者: shengnan007    时间: 2012-9-18 12:44
呃。。。是我啊。。。
作者: shengnan007    时间: 2012-9-18 12:44
PenPen 发表于 2012-9-18 12:40
5 A0 P+ a2 i0 t+ Y2 C2 d您是和邓侃一起写文章的盛楠么?
) I5 o% V2 o3 F! S
是我啊。。。这都能被认出来。。。
作者: PenPen    时间: 2012-9-18 12:47
shengnan007 发表于 2012-9-18 12:44 7 a. V6 f+ x/ v, a9 @  \2 c# v+ v
是我啊。。。这都能被认出来。。。
8 F* A8 Z' S2 ~& B$ u1 o' f8 E$ I% b
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
作者: shengnan007    时间: 2012-9-18 12:49
PenPen 发表于 2012-9-18 12:47 , |" Y& @; T, ~6 E+ S
这篇文章我读过。开始以为是转贴的,后来再一看id就发现真相了~
9 B8 q* o, I8 |5 l  ~0 i1 t
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会员是么?
作者: 不爱吱声    时间: 2012-9-18 12:51
shengnan007 发表于 2012-9-17 22:49 % ]1 g: ]) s0 e, b' G; F$ D
多谢支持。还有两篇一会帖过来。后续的还在写。边看源码边写,比较慢,hoho。这里是要推荐才能变成正式会 ...
& ^% U4 A( t' a8 ?
欢迎,欢迎,已经给你变成正式会员了。
作者: shengnan007    时间: 2012-9-18 12:57
不爱吱声 发表于 2012-9-18 12:51 . t. {3 `% g5 l( q5 T9 X
欢迎,欢迎,已经给你变成正式会员了。

" j) {8 Q# O1 g多谢多谢啦~~
作者: 巴山    时间: 2012-9-19 03:38
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。1 e* l# ?0 v8 m  k! p' H$ m+ P( G) M

4 S4 g6 c% h2 J* d- `; b) Y
作者: 梦晓半生    时间: 2012-9-19 04:21
谢谢。. [( e) z. t" ^
. W+ I1 x5 ]% ^: Z) [
中文看得真累,大部分还是英文术语。% Q* L/ p4 p' r- \' a' ^
; q* c, }; Z1 S4 B9 {0 c
这应该是一个系列吧,后面怎样寻找,执行指令等开始入门,还是说的太简单了。5 Y: h& O0 y6 U7 Y( h

) f1 k: U7 Z1 R- k2 [7 M现在distributed DB在那些大网站很重要,现在开始有跟已有DB分庭抗礼的苗头,不过不是那里工作的话,其中的奥妙大概难说清楚。
作者: shengnan007    时间: 2012-9-19 08:40
巴山 发表于 2012-9-19 03:38 # \  \7 b* W( w9 X& V, R3 U. Q
我们现在的 technology stack 就是 php + mongodb,涉及财务方面的东西用 postgres。
7 C# e9 J2 K/ P& q: Q+ o
/ k% v, b. j3 m ...

) U- q1 l) @+ h- O  x3 h, amongoDB作为存储是没有问题的,财务这种核心数据,还是不建议使用mongoDB的
作者: shengnan007    时间: 2012-9-19 08:44
梦晓半生 发表于 2012-9-19 04:21
4 S; \4 j% g' Y5 X" Q4 p6 i谢谢。
. V$ f3 ~) U" U3 @# f. _
4 g3 M( K' f/ c. [! h8 X+ G1 I中文看得真累,大部分还是英文术语。
$ a6 V$ r+ R8 T/ p
现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体系。这个系列文章的目的,是让大家了解mongoDB的基本的运行机理,这样以后使用的时候,可以知其所以然。但是由于这方面的资料很少,我也是到处找资料,写了这么几篇,再往后,就是边使用,边看源码,边写了。
作者: profer    时间: 2012-9-19 14:16
shengnan007 发表于 2012-9-18 12:44 1 p" W0 b' L; h
是我啊。。。这都能被认出来。。。

- M0 {6 H$ M( O/ ~是邓嫂么?
作者: shengnan007    时间: 2012-9-19 14:17
profer 发表于 2012-9-19 14:16
# y* C0 {( g0 ^5 E9 A! [是邓嫂么?

' s3 V( q6 @& s' L6 y2 i8 @0 l是邓的小兵
作者: 恶魔吹笛来    时间: 2012-9-19 18:35
有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
作者: 梦晓半生    时间: 2012-9-20 00:57
shengnan007 发表于 2012-9-19 08:44
9 f) f. w& D# M- [/ E+ s4 K现在关于mongoDB的文章,大部分都是在告诉大家怎么用,涉及到内部运行机理的文章,数量不多,而且不成体 ...
  H: l0 o9 Z1 }6 b0 c! q
太好了,期待中,希望都带上英文reference。. Y& j& U  _! s' d6 @" y

+ L0 p/ ~& \. C) l$ q" S  V现在这种新技术很多,Mongo是比较流行的一个,我这里附带一下一堆NoSQL的新系统,到最后估计会有几个胜出。
! K8 g1 M. g1 ?; K3 }* c! I
; B6 m% T5 i$ b( J" A) Ghttp://en.wikipedia.org/wiki/NoSQL
作者: shengnan007    时间: 2012-9-20 08:53
梦晓半生 发表于 2012-9-20 00:57 4 M4 j% v) \1 d) J
太好了,期待中,希望都带上英文reference。
+ f( c% ^; |1 h2 G/ P/ P) h, n
现在这种新技术很多,Mongo是比较流行的一个,我这里附带一 ...

0 u1 w) z& y! g6 \" v: q现在写的也很纠结,资料太少了,哈哈
作者: 梦晓半生    时间: 2012-9-21 11:52
shengnan007 发表于 2012-9-20 08:53
( z& D. [( d# u7 Q; M& d现在写的也很纠结,资料太少了,哈哈
' b6 Z6 y. [+ {8 f& P7 i! S
建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
; I7 j5 H; S: c0 ]9 c2 y8 j8 e8 M1 D0 a% i3 [. K" H7 F2 I  O
http://en.wikipedia.org/wiki/NoSQL
; v8 p  ]2 F& o' l( F6 ^# Y& e9 K# I9 G& A! G( {) N, h$ k3 p

作者: 定风波    时间: 2012-9-21 17:03
恶魔吹笛来 发表于 2012-9-19 18:35
% f) x- b" t/ B5 N* Q& v有点惊讶 居然在这里看到这篇文章 呵呵 静待大作
% M- A* F4 ]1 O/ j3 n
有什么可惊讶的邓侃在前一个爱坛版本是很早的注册用户呢,从开心网一块迁移的。。。
作者: shengnan007    时间: 2012-9-24 09:11
梦晓半生 发表于 2012-9-21 11:52 " G4 Y4 x( v4 e
建议从NoSQL写起,这是推动新数据库设计的需求关系,原始动力。
3 z$ v$ e( z; j" [: W6 e
" h) T' |6 o$ \http://en.wikipedia.org/wiki/NoSQL

* _- [& O) r( }  u/ M9 t# e9 `好的好的,现在这个写完,然后开始写nosql




欢迎光临 爱吱声 (http://www.aswetalk.net/bbs/) Powered by Discuz! X3.2