MongoDB数据文件内部结构
openkk 13年前
<p> 有人在 Quora 上提问:<a title="查看 MongoDB 的全部文章" href="/misc/goto?guid=4958202974526448751" target="_blank">MongoDB</a><a title="查看数据文件的全部文章" href="/misc/goto?guid=4958202975293920114" target="_blank">数据文件</a>内部的组织<a title="查看结构的全部文章" href="/misc/goto?guid=4958202976044956159" target="_blank">结构</a>是什么样的。随后 10gen 的工程师 <a href="/misc/goto?guid=4958202976789591266" target="_blank">Jared Rosoff</a> 出来做了简短的回答。</p> <p> 每一个数据库都有自己独立的文件。如果你开启了 directoryperdb 选项,那你每个库的文件会单独放在一个文件夹里。</p> <p> 数据库文件在内部会被切分成单个的块,每个块只保存一个名字空间的数据。在 MongoDB 中,名字空间用于区分不同的存储类别。比如每个 collection 有一个独立的名字空间,每个索引也有自己的名字空间。</p> <p> 在一个块中,会保存多条记录,每条记录是 BSON 格式的,记录与记录之间通过双向链表进行连接。</p> <p> 索引数据也存在数据文件中,不过索引是被组织成B-Tree 结构,而不是双向链表。</p> <p> 对每个数据库,有一个命名空间文件,用于保存每个名字空间对应的元数据。我们通过查询这些元数据来找到对应的名字空间的存储块位置。</p> <p> 如果你开启了 jorunaling 日志,那么还会有一些文件存储着你所有的操作记录。</p> <p> 下面图片摘自 10gen 工程师 Mathias Stearn 在 MongoSV2011 大会上的发言稿,手绘的数据文件结构。</p> <p> <strong>1. 每个数据库有相应的数据文件和命名空间文件</strong></p> <p style="text-align:center;"><img style="width:564px;height:374px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/bae174185d577e00701fdc0c6f600d51.jpg" /></p> <p> <strong>2. 数据文件从 16MB 开始,新的数据文件比上一个文件大一倍,最大为 2GB</strong></p> <p style="text-align:center;"><img style="width:571px;height:379px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/c746bc248cd54c90251686c7790d414a.jpg" /></p> <p> <strong>3. 文件使用 MMAP 进行内存映射,会将所有数据文件映射到内存中,但是只是虚拟内存,只有访问到这块数据时才会交换到物理内存。</strong></p> <p style="text-align:center;"><img style="width:564px;height:374px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/483448852f17def839ff980a156f8314.jpg" /></p> <p style="text-align:center;"><img style="width:568px;height:377px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/9c2d6742888ee21d3c1a858a322b8082.jpg" /></p> <p> <strong>4. MongoDB 的数据文件映射到内存表中的位置</strong></p> <p style="text-align:center;"><img style="width:551px;height:365px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/6f44652fae31c6702f9e28ad4e1c0c2c.jpg" /></p> <p style="text-align:center;"><img style="width:561px;height:372px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/d8967ff3fa6ea7df13f09404f7390205.jpg" /></p> <p> <strong>5. 使用 32 位机器的话,内存地址最大可以标识 4GB 内存</strong></p> <p style="text-align:center;"><img style="width:565px;height:375px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/369468dfbae5e398ba7a46077060485b.jpg" /></p> <p style="text-align:center;"><img style="width:558px;height:370px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/c0d986736fe9f960be41037b2173611d.jpg" /></p> <p> <strong>6. 但是在 32 位机器上,4GB 内存会有 1GB 被内核战胜,大约0.5GB 会用于 mongod 进程的 stack 空间,只剩下大约2.5GB 可用于映射数据文件。</strong></p> <p style="text-align:center;"><img style="width:554px;height:367px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/f079937c787aa75700b5aa62dae5c847.jpg" /></p> <p style="text-align:center;"><img style="width:576px;height:382px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/7fec48c0f3942afb2cfc54f44b35f352.jpg" /></p> <p style="text-align:center;"><img style="width:580px;height:385px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/e509644c9be75210ad1360aece4a3322.jpg" /></p> <p> <strong>7. 在 64 位机器上则最多可以表示 128TB 的空间</strong></p> <p style="text-align:center;"><img style="width:561px;height:372px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/0085eafadf02c014de513f893a2295a7.jpg" /></p> <p style="text-align:center;"><img style="width:567px;height:376px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/e7c9f40bb03cd659c9c8c9dfa52a3612.jpg" /></p> <p style="text-align:center;"><img style="width:562px;height:373px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/7827292b35b2b639804952bd88e9418b.jpg" /></p> <p> <strong>8. 每个数据文件会被分成一个一个的数据块,块与块之间用双向链表连接</strong></p> <p style="text-align:center;"><img style="width:556px;height:369px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/0df18273c5ac7b46564dc629d50f61b9.jpg" /></p> <p style="text-align:center;"><img style="width:572px;height:379px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/9fad53f41151f0ec2145ca18dc06e6f5.jpg" /></p> <p> <strong>9. 在名字空间文件中,保存了每个名字空间的存储信息元数据,包括其大小,块数,第一块位置,最后一块位置,被删除的块的链表以及索引信息</strong></p> <p style="text-align:center;"><img style="width:571px;height:379px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/a32187db392f07735e3d483f82b689a7.jpg" /></p> <p style="text-align:center;"><img style="width:556px;height:369px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/1cd69088c40225319b6ee14959ec1256.jpg" /></p> <p> <strong>10. 这些位置通过 DiskLoc 数据结构进行存储,存储了数据文件编号和块在文件中的位置</strong></p> <p style="text-align:center;"><img style="width:568px;height:377px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/59ca625b35e84f5c45543f3d4f6d4b4a.jpg" /></p> <p style="text-align:center;"><img style="width:561px;height:372px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/f04630b8481212dbc71e0772cef133c2.jpg" /></p> <p style="text-align:center;"><img style="width:576px;height:382px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/0cc145bbf221902c0a53d8d37c46d64e.jpg" /></p> <p style="text-align:center;"><img style="width:550px;height:386px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/1aba3a4d28608ad3d87c2d2950239cff.jpg" /></p> <p> <strong>11. 对每一个块来说,其头部包含了一些块的元数据,比如自己的位置,上一个和下一个块的位置以及块中第一条和最后一条记录的位置指针。剩下的部分用于存储具体的数据,具体数据之间也是通过双向链接来进行连接。</strong></p> <p style="text-align:center;"><img style="width:558px;height:370px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/4af3c64a59936e4f754a41e724dc3dc4.jpg" /></p> <p style="text-align:center;"><img style="width:573px;height:380px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/9f637c5bac17fe868a9607a4392005bc.jpg" /></p> <p style="text-align:center;"><img style="width:562px;height:373px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/fee801a997f726a5cf43c1a0d2e1876f.jpg" /></p> <p> <strong>12. 下面是B-Tree 的存储结构和工作原理</strong></p> <p style="text-align:center;"><img style="width:580px;height:385px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/cf41bbbb2f319b510f4ece5bdd8b9e61.jpg" /></p> <p style="text-align:center;"><img style="width:564px;height:374px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/d9033fe8463a85b284aff57a1da49fba.jpg" /></p> <p style="text-align:center;"><img style="width:583px;height:387px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/216af81279b230ef05113d2825bdd6c5.jpg" /></p> <p style="text-align:center;"><img style="width:555px;height:368px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/a1a844284184eeb971661fc5a8e3726d.jpg" /></p> <p style="text-align:center;"><img style="width:546px;height:362px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/1156f43c058324b581bedfe732b3bcab.jpg" /></p> <p style="text-align:center;"><img style="width:564px;height:374px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/252266c6a1413311d963cdc275d78b2e.jpg" /></p> <p style="text-align:center;"><img style="width:582px;height:386px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/2ae4735c994a10b6de5915171eb00a0a.jpg" /></p> <p style="text-align:center;"><img style="width:568px;height:377px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/d9e360163678711b4786050c012c90d3.jpg" /></p> <p style="text-align:center;"><img style="width:582px;height:386px;" alt="MongoDB数据文件内部结构" src="https://simg.open-open.com/show/f30c800202e96b37b985cb69c8735733.jpg" /></p> 来自: <a id="link_source2" href="/misc/goto?guid=4958202977531340417" target="_blank">blog.nosqlfan.com</a>