分片服务角色介绍
1,客户端访问路由节点mongos来进行数据读写。
config服务器保存了两个映射关系,一个是key值的区间对应哪一个chunk的映射关系,另一个是chunk存在哪一个分片节点的映射关系。
路由节点通过config服务器获取数据信息,通过这些信息,找到真正存放数据的分片节点进行对应操作。
2,路由节点还会在写操作时判断当前chunk是否超出限定大小,如果超出,就分列成两个chunk。
对于按分片key进行的查询和update操作来说,路由节点会查到具体的chunk然后再进行相关的工作。
对于不按分片key进行的查询和update操作来说,mongos会对所有下属节点发送请求然后再对返回结果进行合并。
=============================================
数据文件内部结构
在文件系统中为每个数据库预分配逐渐增长大小的文件集,这样可以有效地避免潜在的文件系统碎片,使数据库操作更高效。
一个数据库的文件集从序号0开始分配,0,1...,大小依次是64M,128M,256M,512M,1G,2G,然后就是一直2G的创建下去(32位系统最大到512M)。
数据库文件在内部会被切分成多个数据域,数据域之间使用双向链表连接。
名字空间用于区分不同的存储类别,比如每个collection有一个独立的名字空间,每个索引也有自己的名字空间
=============================================
字空间与数据域:
每个名字空间可以有不同的数据域,在磁盘上不必连续。
图中还有一个特殊的名字空间freelist,存放着不再使用的数据域,例如,删除集合或索引产生的数据域。
当名字空间分配新的数据域时,系统会先查找空闲列表,看看有没有适合大小的数据域可用。
在每一个数据域中,保存了具体一行行BSON格式的数据,这些数据也是通过双向链表连接。
每一行数据存储空间不仅包括数据占用空间,还可能包含一部分附加空间,这使得在数据update变大后可以不移动位置。
索引数据也保存在数据文件中,不过索引是被组织成B-tree结构,而不是双向链表。
对每个数据库,都有一个命名空间文件,用于保存每个名字空间对应的元数据。我们通过查询这些元数据来找到对应的名字空间的数据存储位置。
数据文件使用MMAP进行内存映射,会将所有数据文件映射到内存中,但只是虚拟内存,只有访问到这块数据时才会交换到物理内存
在命名空间文件中,保存的是一个哈希表,存储了每个名字空间对应的元数据,包括其大小,块数,第一块位置,最后一块位置,被删除的块的链表以及索引信息
这些位置通过DiskLoc数据结构进行存储,存储了数据文件编号和块在文件中的位置
MongoDB尽管在数据存储上与传统关系数据库很不一样,但是在索引构建上却几乎是与传统关系型数据库一致。
主要是使用了B-tree作为索引结构。
B-tree,多路搜索树,并不是二叉的,以下介绍其主要特点:
============================================================
唯一索引
想像你要在一本没有目录的食谱上查找某一道菜的做法,唯一的办法可能就是从头到尾把这本几百页的书看一遍,直到找到你想找的菜。
而一个快速的方法就是给菜谱加上一个目录,目录中有每一道菜的名字及与其相对应的页数,并且菜名是按字母顺序排列,这样你就可以按首字母快速地找到你菜谱的页数了。
唯一索引
举例:
水饺
- 45
水煮肉片
- 4,011
水煮鱼
- 943
===================
非唯一索引
但是如果我今天买了条鱼,想查一下所有跟鱼相关的做法,那么用上面的索引就没办法了。于是出现下面一种索引构建方法,即将所有菜的材料构建目录,这时候一个材料对应多道菜。
举例:
鱼
- 3, 20, 42, 88, 103, 1,215…
猪肉
- 2, 47, 88, 89, 90, 275…
白菜
- 7, 9, 80, 81, 82, 83, 84…
==================
联合索引
还有另一种需求,如果我知道材料里有鱼,而我又知道这道菜的名字,就不用查找到材料后去翻看后面几个具体页的菜再来选择了。
举例:
鱼
- 水煮鱼
—- 1,215
- 红烧带鱼
—- 88
- 酸菜鱼
—- 103
=====================
mngodb api用法
1,DBCollection
DBCollection
insert与save的区别
若存在主键,insert() 不做操作,而save() 则更改原来的内容为新内容