Summary of MongoDB knowledge points

MongoDB

NOSQL

NoSQL: Not Only SQL is essentially a database technology. Compared with traditional database technology, it does not follow some constraints, such as: SQL standards, ACID attributes, table structure, etc.

What is MongoDB

MongoDB:是一个数据库 ,高性能、无模式、文档性,目前nosql中最热门的数据库,开源产品,基于c++开发。是nosql数据库中功能最丰富,最像关系数据库的。
特点:
	1,面向集合文档的存储:适合存储Bson(json的扩展)形式的数据;
	2,格式自由,数据格式不固定,生产环境下修改结构都可以不影响程序运行;
	3,强大的查询语句,面向对象的查询语言,基本覆盖sql语言所有能力;
	4,完整的索引支持,支持查询计划;
	5,支持复制和自动故障转移;
	6,支持二进制数据及大型对象(文件)的高效存储;
	7,使用分片集群提升系统扩展性;
	8,使用内存映射存储引擎,把磁盘的IO操作转换成为内存的操作;

适用场合:
	1,网站数据:Mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
	3,缓存:由于性能很高,Mongo也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo搭建的持久化缓存层可以避免下层的数据源 过载。
	4,大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
	5,高伸缩性的场景:Mongo非常适合由数十或数百台服务器组成的数据库。Mongo的路线图中已经包含对MapReduce引擎的内置支持。
	6,用于对象及JSON数据的存储:Mongo的BSON数据格式非常适合文档化格式的存储及查询。

MongoDB should pay attention to the problem

1. Because MongoDB is fully indexed, it directly puts the index in memory, so it supports up to 2.5G of data. If it is 64-bit, it will be more.
2. Because there is no recovery mechanism, it is necessary to make a data backup
3, because the default listening address is 127.0.0.1, so authentication is required, otherwise it is not safe enough; if it is used by yourself, it is recommended to configure it as localhost hostname
4, which is ensured by GetLastError change.

MongoDB data structure

MongoDB中存储的对象时BSON,是一种类似JSON的二进制文件,它是由许多的键值对组成。
而数据库的整体结构组成如下:
	键值对--》文档--》集合--》数据库--》实例
MongoDB中的key命名规则如下:
	1,"\0"不能使用
	2,带有"."号,"_"号和"$"号前缀的Key被保留
	3,大小写有区别,Age不同于age
	4,同一个文档不能有相同的Key
	5,除了上面几条规则外,其他所有UTF-8字符都可以使用

Common commands

进入数据库:
	use admin
增加或修改密码:
	db.addUser('xingoo','123')
	db.addUser("xingoo","123",true) 参数分别为 用户名、密码、是否只读
查看用户列表:
	db.system.users.find()
查看所有数据库:
	show dbs

Storage engine

在3.2版本之前MMAPV1是默认的存储引擎,其采用linux操作系统内存映射技术,但一直饱受诟病;3.4以上版本默认的存储引擎是wiredTiger。
比较:
	1,读写操作性能更好,WiredTiger能更好的发挥多核系统的处理能力;
	2,MMAPV1引擎使用表级锁,当某个单表上有并发的操作,吞吐将受到限制。WiredTiger使用文档级锁,由此带来并发及吞吐的提高
	3,相比MMAPV1存储索引时WiredTiger使用前缀压缩,更节省对内存空间的损耗;
	4,提供压缩算法,可以大大降低对硬盘资源的消耗,节省约60%以上的硬盘资源;

How to deal with mongodb data loss

在存入mongo的时候,会先存入内存中的缓存中,当缓存的大小到达2G或者达到60S的时候会同步到磁盘中,同时可以设置Journal缓冲区每100毫秒向磁盘中的Journal日志同步一次操作命令,这样来确保数据不丢失,同时可以通过设置写策略进一步确保。
注意:
	Journaling类似于关系数据库中的事务日志。Journaling能够使MongoDB数据库由于意外故障后快速恢复。MongoDB2.4版本后默认开启了Journaling日志功能,mongod实例每次启动时都会检查journal日志文件看是否需要恢复。由于提交journal日志会产生写入阻塞,所以它对写入的操作有性能影响,但对于读没有影响。在生产环境中开启Journaling是很有必要的。
写策略:
	写策略配置:{ w: <value>, j: <boolean>, wtimeout: <number> }
	w: 数据写入到number个节点才向用客户端确认
		{w: 0} 对客户端的写入不需要发送任何确认,适用于性能要求高,但不关注正确性的场景
		{w: 1} 默认的writeConcern,数据写入到Primary就向客户端发送确认
		{w: “majority”} 数据写入到副本集大多数成员后向客户端发送确认,适用于对数据安全性要求比较高的场景,该选项会降低写入性能

	j: 写入操作的journal持久化后才向客户端确认
  		默认为{j: false},如果要求写入持久化了才向客户端确认,则指定该选项为true

  	wtimeout: 写入超时时间,仅w的值大于1时有效。
		当指定{w: }时,数据需要成功写入number个节点才算成功,如果写入过程中有节点故障,可能导致这个条件一直不能满足,从而一直不能向客户端发送确认结果,针对这种情况,客户端可设置wtimeout选项来指定超时时间,当写入过程持续超过该时间仍未结束,则认为写入失败。

java代码实现写策略:
	通过WriteConcern,策略配置如下:
		UNACKNOWLEDGED:不等待服务器返回或确认,仅可以抛出网络异常;
		ACKNOWLEDGED:默认配置,等待服务器返回结果;
		JOURNALED:等待服务器完成journal持久化之后返回;
		W1 :等待集群中一台服务器返回结果;
		W2 :等待集群中两台服务器返回结果;
		W3 :等待集群中三台服务器返回结果;
		MAJORITY:等待集群中多数服务器返回结果;

index

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。索引主要用于排序和检索。
MongoDB使用 ensureIndex() 方法来创建索引,ensureIndex()方法基本语法格式如下所示:
  db.collection.createIndex(keys, options)
  语法中 Key 值为要创建的索引字段,1为指定按升序创建索引,如果你想按降序来创建索引指定为-1,也可以指定为hashed(哈希索引)。

索引属性:
	background:是否后台构建索引,在生产环境中,如果数据量太大,构建索引可能会消耗很长时间,为了不影响业务,可以加上此参数,后台运行同时还会为其他读写操作让路,这个建议配置为true开启,这样来提高效率。

	unique:是否为唯一索引

索引类型:
	单键索引:
		在某一个特定的属性上建立索引,例如:db.users. createIndex({age:-1});
		1,mongoDB在ID上建立了唯一的单键索引,所以经常会使用id来进行查询;
		2,在索引字段上进行精确匹配、排序以及范围查找都会使用此索引;

	复合索引:
		在多个特定的属性上建立索引,例如:db.users. createIndex({username:1,age:-1,country:1});
		1,复合索引键的排序顺序,可以确定该索引是否可以支持排序操作;
		2,在索引字段上进行精确匹配、排序以及范围查找都会使用此索引,但与索引的顺序有关;
		3,为了性能考虑,应删除存在与第一个键相同的单键索引

	多键索引:
		在数组的属性上建立索引,例如:db.users. createIndex({favorites.city:1});

	哈希索引:
		不同于传统的B-树索引,哈希索引使用hash函数来创建索引。
		1,在索引字段上进行精确匹配,但不支持范围查询,不支持多键hash;
		2,Hash索引上的入口是均匀分布的,在分片集合中非常有用;

optimization

1,开启内置的查询分析器,记录读写操作效率:
	db.setProfilingLevel(n,{m}),n的取值可选0,1,2;
		0是默认值表示不记录;
		1表示记录慢速操作,如果值为1,m必须赋值单位为ms,用于定义慢速查询时间的阈值;
		2表示记录所有的读写操作;

2,,分析慢速查询
	就是查看执行计划,使用explain分析慢速查询。
	explain的入参可选值为:
		"queryPlanner":是默认值,表示仅仅展示执行计划信息;
		"executionStats":表示展示执行计划信息同时展示被选中的执行计划的执行情况信息;
		"allPlansExecution":表示展示执行计划信息,并展示被选中的执行计划的执行情况信息,还展示备选的执行计划的执行情况信息

3,合理建立索引
	建立索引的规则:
		1,索引很有用,但是它也是有成本的——它占内存,让写入变慢;
		2,mongoDB通常在一次查询里使用一个索引,所以多个字段的查询或者排序需要复合索引才能更加高效;
		3,复合索引的顺序非常重要,例如此脚本所示:
		4,在生成环境构建索引往往开销很大,时间也不可以接受,在数据量庞大之前尽量进行查询优化和构建索引;
		5,避免昂贵的查询,使用查询分析器记录那些开销很大的查询便于问题排查;
		6,通过减少扫描文档数量来优化查询,使用explain对开销大的查询进行分析并优化;
		7,索引是用来查询小范围数据的,不适合使用索引的情况:
			1,每次查询都需要返回大部分数据的文档,避免使用索引
			2,写比读多

	优化目标:
		1,根据需求建立索引
		2,每个查询都要使用索引以提高查询效率, winningPlan. stage 必须为IXSCAN ;
		3,追求totalDocsExamined = nReturned

High availability

1,可复制集
	可复制集是跨多个MongDB服务器(节点)分布和维护数据的方法。mongoDB可以把数据从一个节点复制到其他节点并在修改时进行同步,集群中的节点配置为自动同步数据;旧方法叫做主从复制,mongoDB 3.0以后推荐使用可复制集;
	作用:
		1,避免数据丢失,保障数据安全,提高系统安全性;
			(最少3节点,最大50节点)
		2,自动化灾备机制,主节点宕机后通过选举产生新主机;提高系统健壮性;
			(7个选举节点上限)
		3,读写分离,负载均衡,提高系统性能;
		4,生产环境推荐的部署模式;
	原理:
		数据同步:从节点与主节点保持长轮询;1.从节点查询本机oplog最新时间戳;2.查询主节点oplog晚于此时间戳的所有文档;3.加载这些文档,并根据log执行写操作;
		阻塞复制:与writeconcern相关,不需要同步到从节点的策略(如: acknowledged Unacknowledged 、w1),数据同步都是异步的,其他情况都是同步;
		心跳机制:成员之间会每2s 进行一次心跳检测(ping操作),发现故障后进行选举和故障转移;
		选举制度:主节点故障后,其余节点根据优先级和bully算法选举出新的主节点,在选出主节点之前,集群服务是只读的;
	注意:
		MongoDB复制集里Primary节点是不固定的,所以生产环境千万不要直连Primary。

2,分片集群
	分片是把大型数据集进行分区成更小的可管理的片,这些数据片分散到不同的mongoDB节点,这些节点组成了分片集群。
	作用:
		1,数据海量增长,需要更大的读写吞吐量:存储分布式
		2,单台服务器内存、cpu等资源是有瓶颈的:负载分布式
	注意:分片集群是个双刃剑,在提高系统可扩展性和性能的同时,增大了系统的复杂性,所以在实施之前请确定是必须的。
	容易发生的状况:
		请求分流:通过路由节点将请求分发到对应的分片和块中;
		数据分流:内部提供平衡器保证数据的均匀分布,数据平均分布式请求平均分布的前提;
		块的拆分:3.4版本块的最大容量为64M或者10w的数据,当到达这个阈值,触发块的拆分,一分为二;
		块的迁移:为保证数据在分片节点服务器分片节点服务器均匀分布,块会在节点之间迁移。一般相差8个分块的时候触发;
		
	分片注意点:
		热点 :某些分片键会导致所有的读或者写请求都操作在单个数据块或者分片上,导致单个分片服务器严重不堪重负。自增长的分片键容易导致写热点问题;
		不可分割数据块:过于粗粒度的分片键可能导致许多文档使用相同的分片键,这意味着这些文档不能被分割为多个数据块,限制了mongoDB均匀分布数据的能力;
		查询障碍:分片键与查询没有关联,造成糟糕的查询性能。 
	建议:
		1,不要使用自增长的字段作为分片键,避免热点问题;
		2,不能使用粗粒度的分片键,避免数据块无法分割;
		3,不能使用完全随机的分片键值,造成查询性能低下;
		4,使用与常用查询相关的字段作为分片键,而且包含唯一字段(如业务主键,id等);
		5,索引对于分区同样重要,每个分片集合上要有同样的索引,分片键默认成为索引;分片集合只允许在id和分片键上创建唯一索引;

Guess you like

Origin blog.csdn.net/qq_28822933/article/details/88362388