MongoDB 构架图分享
openkk 12年前
<div id="news_body"> <p> 本文图片来自 Ricky Ho 的博文 <a href="/misc/goto?guid=4958336597051101665" target="_blank">MongoDB 构架</a>(<a title="查看 MongoDB 的全部文章" href="/misc/goto?guid=4958202974526448751" target="_blank">MongoDB</a> Architecture),这是个一听就感觉很宽泛的话题,但是作者在文章中确实对 MongoDB 由内至外的<a title="查看架构的全部文章" href="/misc/goto?guid=4958336598606633975" target="_blank">架构</a>进行了剖析。本文截取了其文章中的几张重点架构示意图片进行简单描述。希望对大家有用。</p> <p> <strong>MongoDB 数据文件内部结构</strong></p> <p style="text-align:center;"><a target="_blank"><img style="width:551px;height:382px;" alt="MongoDB 构架图分享" src="https://simg.open-open.com/show/be41f6cd9263ded73d2c9739bc6370e6.jpg" /></a></p> <ol> <li>MongoDB 在数据存储上按命名空间来划分,一个 collection 是一个命名空间,一个索引也是一个命名空间</li> <li>同一个命名空间的数据被分成很多个 Extent,Extent 之间使用双向链表连接</li> <li>在每一个 Extent 中,保存了具体每一行的数据,这些数据也是通过双向链接连接的</li> <li>每一行数据存储空间不仅包括数据占用空间,还可能包含一部分附加空间,这使得在数据 update 变大后可以不移动位置</li> <li>索引以 BTree 结构实现</li> </ol> <p> <strong>在 MongoDB 中实现事务</strong></p> <p style="text-align:center;"><a target="_blank"><img style="width:579px;height:402px;" alt="MongoDB 构架图分享" src="https://simg.open-open.com/show/ee652d656c51f91af0bf83a5f84f1c00.jpg" /></a></p> <p> 众所周知,MongoDB 只支持对单行记录的原子性修改,并不支持对多行数据的原子操作。但是通过上图中的变态操作,实际你也可以自己实现事务。其步骤如图所未:</p> <ul> <li>第 1 步:先记录一条事务记录,将要修改的多行记录的修改值写到里面,并设置其状态为 init(如果这时候操作中断,那么在重新启动时,会判断到他处于 init 状态,从而将其保存的多行修改操作应用到具体的行上)</li> <li>第 2 步:然后更新具体要修改的行,将刚才写的事务记录的标识写到它的 tran 字段中</li> <li>第 3 步:将事务记录的状态从 init 变成 pending(如果在这时候操作中断,那么在重新启动时,会判断到它的状态是 pending 的,这时候查看其所有对应的多条要修改的记录,如果其 tran 有值,那么就进行第 4 步,如果没值,说明第 4 步已经执行过了,直接将其状态从 pending 变成 commited 了就行)</li> <li>第 4 步:将需要修改的多条记录的相应值修改了,并且 unset 掉之前的 tran 字段</li> <li>第 5 步:将事务记录那一条的状态从 pending 变成 commited,事务完成</li> </ul> <p> 其实上面的步骤并不罕见,在支持事务的 DBMS 中,其事务原子性提交的保证大多都与上面类似。其实事务记录的 tran 那条记录,就类似于这些 DBMS 中的 redolog 一样。</p> <p> <strong>MongoDB 数据同步</strong></p> <p style="text-align:center;"><a target="_blank"><img style="width:535px;height:277px;" alt="MongoDB 构架图分享" src="https://simg.open-open.com/show/b86fec297a2ae578f482ccda072ba741.jpg" /></a></p> <p> 上图是 MongoDB 采用 Replica Sets 模式的同步流程</p> <ul> <li>红色箭头表示写操作写到 Primary 上,然后异步同步到多个 Secondary 上</li> <li>蓝色箭头表示读操作可以从 Primary 或 Secondary 任意一个上读</li> <li>各个 Primary 与 Secondary 之间一直保持心跳同步检测,用于判断 Replica Sets 的状态</li> </ul> <p> <strong>分片机制</strong></p> <p style="text-align:center;"><a target="_blank"><img style="width:565px;height:386px;" alt="MongoDB 构架图分享" src="https://simg.open-open.com/show/3ed1c82e9534d48fde6233480a049501.jpg" /></a></p> <ul> <li>MongoDB 的分片是指定一个分片 key 来进行,数据按范围分成不同的 chunk,每个 chunk 的大小有限制</li> <li>有多个分片节点保存这些 chunk,每个节点保存一部分的 chunk</li> <li>每一个分片节点都是一个 Replica Sets,这样保证数据的安全性</li> <li>当一个 chunk 超过其限制的最大体积时,会分裂成两个小的 chunk</li> <li>当 chunk 在分片节点中分布不均衡时,会引发 chunk 迁移操作</li> </ul> <p> <strong>服务器角色</strong></p> <p style="text-align:center;"><a target="_blank"><img style="width:564px;height:344px;" alt="MongoDB 构架图分享" src="https://simg.open-open.com/show/683980c6edff618946dc3615c0162bdc.jpg" /></a></p> <p> 上面讲了分片的标准,下面是具体在分片时的几种节点角色</p> <ul> <li>客户端访问路由节点 mongos 来进行数据读写</li> <li>config 服务器保存了两个映射关系,一个是 key 值的区间对应哪一个 chunk 的映射关系,另一个是 chunk 存在哪一个分片节点的映射关系</li> <li>路由节点通过 config 服务器获取数据信息,通过这些信息,找到真正存放数据的分片节点进行对应操作</li> <li>路由节点还会在写操作时判断当前 chunk 是否超出限定大小,如果超出,就分列成两个 chunk</li> <li>对于按分片 key 进行的查询和 update 操作来说,路由节点会查到具体的 chunk 然后再进行相关的工作</li> <li>对于不按分片 key 进行的查询和 update 操作来说,mongos 会对所有下属节点发送请求然后再对返回结果进行合并</li> </ul> <p> 更多详细内容请看原文:<a href="/misc/goto?guid=4958336597051101665" target="_blank">MongoDB Architecture</a></p> </div> 来自: <a id="link_source2" href="/misc/goto?guid=4958336600129859481" target="_blank">blog.nosqlfan.com</a>