本文重点叙述下mongodb存储特性和内部原理,
下一篇文章我们一块儿来搭建下Replica Sets+Sharded Cluster的集群
复制代码
一、3.0新增引擎 推荐使用 二、能够支撑更高的读写负载和并发量linux
全部的write请求都基于“文档级别”的lock,
所以多个客户端能够同时更新一个colleciton中的不一样文档,
这种更细颗粒度的lock,能够支撑更高的读写负载和并发量。
由于对于production环境,更多的CPU能够有效提高wireTiger的性能,
由于它是的IO是多线程的
复制代码
三、配置缓存web
能够经过在配置文件中指定“cacheSizeGB”参数设定引擎使用的内存量,
此内存用于缓存工做集数据(索引、namespace,未提交的write,query缓冲等)
复制代码
四、journal即预写事务日志mongodb
a、journal就是一个预写事务日志,来确保数据的持久性数据库
b、wiredTiger每隔60秒(默认)或者待写入的数据达到2G时,mongodb将对journal文件提交一个checkpoint(检测点,将内存中的数据变动flush到磁盘中的数据文件中,并作一个标记点,表示此前的数据表示已经持久存储在了数据文件中,此后的数据变动存在于内存和journal日志)缓存
c、对于write操做,首先被持久写入journal,而后在内存中保存变动数据,条件知足后提交一个新的检测点,即检测点以前的数据只是在journal中持久存储,但并无在mongodb的数据文件中持久化,延迟持久化能够提高磁盘效率,若是在提交checkpoint以前,mongodb异常退出,此后再次启动能够根据journal日志恢复数据安全
d、journal日志默认每一个100毫秒同步磁盘一次,每100M数据生成一个新的journal文件,journal默认使用了snappy压缩,检测点建立后,此前的journal日志便可清除。网络
e、mongod能够禁用journal,这在必定程度上能够下降它带来的开支;对于单点mongod,关闭journal可能会在异常关闭时丢失checkpoint之间的数据(那些还没有提交到磁盘数据文件的数据);对于replica set架构,持久性的保证稍高,但仍然不能保证绝对的安全(好比replica set中全部节点几乎同时退出时)多线程
一、原生的存储引擎 直接使用系统级的内存映射文件机制(memory mapped files)架构
二、对于insert、read和in-place update(update不致使文档的size变大)性能较高并发
三、不过MMAPV1在lock的并发级别上,支持到collection级别 因此对于同一个collection同时只能有一个write操做执行 这一点相对于wiredTiger而言,在write并发性上就稍弱一些
四、对于production环境而言,较大的内存可使此引擎更加高效,有效减小“page fault”频率
五、可是由于其并发级别的限制,多核CPU并不能使其受益
六、此引擎将不会使用到swap空间,可是对于wiredTiger而言须要必定的swap空间
七、对于大文件MAP操做,比较忌讳的就是在文件的中间修改数据,并且致使文件长度增加,这会涉及到索引引用的大面积调整
八、全部的记录在磁盘上连续存储,当一个document尺寸变大时,mongodb须要从新分配一个新的记录(旧的record标记删除,新的记record在文件尾部从新分配空间)
九、这意味着mongodb同时还须要更新此文档的索引(指向新的record的offset),与in-place update相比,将消耗更多的时间和存储开支。
十、因而可知,若是你的mongodb的使用场景中有大量的这种update,那么或许MMAPv1引擎并不太适合
十一、同时也反映出若是document没有索引,是没法保证document在read中的顺序(即天然顺序)
十二、3.0以后,mongodb默认采用“Power of 2 Sized Allocations”,因此每一个document对应的record将有实际数据和一些padding组成,这padding能够容许document的尺寸在update时适度的增加,以最小化从新分配record的可能性。此外从新分配空间,也会致使磁盘碎片(旧的record空间)
一、默认状况下,MMAPv1中空间分配使用此策略,每一个document的size是2的次幂,好比3二、6四、12八、256...2MB,若是文档尺寸大于2MB,则空间为2MB的倍数(2M,4M,6M等)
二、2种优点
那些删除或者update变大而产生的磁盘碎片空间(尺寸变大,意味着开辟新空间存储此document,旧的空间被mark为deleted)能够被其余insert重用
再者padding能够容许文档尺寸有限度的增加,而无需每次update变大都从新分配空间。
三、mongodb还提供了一个可选的“No padding Allocation”策略(即按照实际数据尺寸分配空间),若是你确信数据绝大多数状况下都是insert、in-place update,极少的delete,此策略将能够有效的节约磁盘空间,看起来数据更加紧凑,磁盘利用率也更高
备注:mongodb 3.2+以后,默认的存储引擎为“wiredTiger”,大量优化了存储性能,建议升级到3.2+版本
一、尺寸大小是固定值 相似于一个可循环使用的buffer
若是空间被填满以后,新的插入将会覆盖最旧的文档,一般不会对Capped进行删除或者update操做,因此这种类型的collection可以支撑较高的write和read
二、不须要对这种collection构建索引,由于insert是append(insert的数据保存是严格有序的)、read是iterator方式,几乎没有随机读
三、在replica set模式下,其oplog就是使用这种colleciton实现的
四、Capped Collection的设计目的就是用来保存“最近的”必定尺寸的document
db.createCollection("capped_collections",
new CreateCollectionOptions()
.capped(true)
.maxDocuments(6552350)
.usePowerOf2Sizes(false).autoIndex(true));//不会涉及到更新,因此能够不用power of 2
复制代码
五、相似于“FIFO”队列,并且是有界队列 适用于数据缓存,消息类型的存储
六、Capped支持update,可是咱们一般不建议,若是更新致使document的尺寸变大,操做将会失败,只能使用in-place update,并且还须要创建合适的索引
七、在capped中使用remove操做是容许的
八、autoIndex属性表示默认对_id字段创建索引
一、mongodb支持内嵌document 即document中一个字段的值也是一个document
二、若是内嵌文档(即reference文档)尺寸是动态的,好比一个user能够有多个card,由于card数量没法预估,这就会致使document的尺寸可能不断增长以致于超过“Power of 2 Allocate”,从而触发空间从新分配,带来性能开销
三、这种状况下,咱们须要将内嵌文档单独保存到一个额外的collection中,做为一个或者多个document存储,好比把card列表保存在card collection中
四、若是reference文档尺寸较小,能够内嵌,若是尺寸较大,建议单独存储。此外内嵌文档还有个优势就是write的原子性
一、提升查询性能,默认状况下_id字段会被建立惟一索引;
二、由于索引不只须要占用大量内存并且也会占用磁盘,因此咱们须要创建有限个索引,并且最好不要创建重复索引;
三、每一个索引须要8KB的空间,同时update、insert操做会致使索引的调整,
会稍微影响write的性能,索引只能使read操做收益,
因此读写比高的应用能够考虑创建索引
复制代码
好比一个用于存储log的collection,
log分为有两种“dev”、“debug”,结果大体为
{"log":"dev","content":"...."},{"log":"debug","content":"....."}。
这两种日志的document个数比较接近,
对于查询时,即便给log字段创建索引,这个索引也不是高效的,
因此能够考虑将它们分别放在2个Collection中,好比:log_dev和log_debug。
复制代码
mongodb提供了expire机制,
便可以指定文档保存的时长,过时后自动删除,即TTL特性,
这个特性在不少场合将是很是有用的,
好比“验证码保留15分钟有效期”、“消息保存7天”等等,
mongodb会启动一个后台线程来删除那些过时的document
须要对一个日期字段建立“TTL索引”,
好比插入一个文档:{"check_code":"101010",$currentDate:{"created":true}}},
其中created字段默认值为系统时间Date;而后咱们对created字段创建TTL索引:
collection.createIndex(new Document("created",1),new IndexOptions().expireAfter(15L,TimeUnit.MILLISECONDS));//15分钟
向collection中insert文档时,created的时间为系统当前时间,
其中在creatd字段上创建了“TTL”索引,索引TTL为15分钟,
mongodb后台线程将会扫描并检测每条document的(created时间 + 15分钟)与当前时间比较,
若是发现过时,则删除索引条目(连带删除document)。
某些状况下,可能须要实现“在某个指定的时刻过时”,
只须要将上述文档和索引变通改造便可,
即created指定为“目标时间”,expiredAfter指定为0。
复制代码
一般是三个对等的节点构成一个“复制集”集群,
有“primary”和secondary等多种角色
其中primary负责读写请求,secondary能够负责读请求,这又配置决定,
其中secondary紧跟primary并应用write操做;
若是primay失效,则集群进行“多数派”选举,选举出新的primary,即failover机制,即HA架构。
复制集解决了单点故障问题,也是mongodb垂直扩展的最小部署单位,
固然sharding cluster中每一个shard节点也可使用Replica set提升数据可用性。
复制代码
数据水平扩展的手段之一;
replica set这种架构的缺点就是“集群数据容量”受限于单个节点的磁盘大小,
若是数据量不断增长,对它进行扩容将时很是苦难的事情,因此咱们须要采用Sharding模式来解决这个问题。
将整个collection的数据将根据sharding key被sharding到多个mongod节点上,
即每一个节点持有collection的一部分数据,这个集群持有所有数据,
原则上sharding能够支撑数TB的数据。
复制代码
建议mongodb部署在linux系统上,较高版本,选择合适的底层文件系统(ext4),开启合适的swap空间
不管是MMAPV1或者wiredTiger引擎,较大的内存总能带来直接收益
对数据存储文件关闭“atime”(文件每次access都会更改这个时间值,表示文件最近被访问的时间),能够提高文件访问效率
ulimit参数调整,这个在基于网络IO或者磁盘IO操做的应用中,一般都会调整,上调系统容许打开的文件个数(ulimit -n 65535)。
mongodb的数据将会保存在底层文件系统中,
好比咱们dbpath设定为“/data/db”目录,
咱们建立一个database为“test”,collection为“sample”,
而后在此collection中插入数条documents。咱们查看dbpath下生成的文件列表:
复制代码
能够看到test这个数据库目前已经有6个数据文件(data files),
每一个文件以“database”的名字 + 序列数字组成,
序列号从0开始,逐个递增,数据文件从16M开始,每次扩张一倍(16M、32M、64M、128M...),
在默认状况下单个data file的最大尺寸为2G,
若是设置了smallFiles属性(配置文件中)则最大限定为512M;
mongodb中每一个database最多支持16000个数据文件,即约32T,
若是设置了smallFiles则单个database的最大数据量为8T。
若是你的database中的数据文件不少,
可使用directoryPerDB配置项将每一个db的数据文件放置在各自的目录中。
当最后一个data file有数据写入后,
mongodb将会当即预分配下一个data file,
能够经过“--nopreallocate”启动命令参数来关闭此选项
复制代码
https://blog.csdn.net/quanmaoluo5461/article/details/85164588
复制代码