1.什么场景应该用 MongoDB ?http://www.mongoing.com/archives/3609
2. MongoDB目前3大核心优势:『灵活模式』+ 『高可用性』 + 『可扩展性』,通过json文档来实现灵活模式,通过复制集来保证高可用,通过Sharded cluster来保证可扩展性。
3.mongodb 事务:MongoDB does not support multi-document transactions.However, MongoDB does provide atomic operations on a single document. Often these document-level atomic operations are sufficient to solve problems that would require ACID transactions in a relational database.For example, in MongoDB, you can embed related data in nested arrays or nested documents within a single document and update the entire document in a single atomic operation. Relational databases might represent the same kind of data with multiple tables and rows, which would require transaction support to update the data atomically.
不支持复杂的多文档事务,但复杂事务不是必须的,在mongodb中对单一文档的所有操作都原子操作(包括对其中嵌入文档的操作),加上它支持友好的更新语法使得关系数据库中很多需要事务的地方在MongoDB中可以用其他的操作来实现。如果必须要支持事务,用两阶段提交法,
官网例子:https://docs.mongodb.com/manual/tutorial/perform-two-phase-commits/
4.存储引擎,最新的mongo默认存储引擎是wiredTiger,支持文档级别的锁(也就是行级锁),主要有排他锁,共享锁,意向共享锁,意向排他锁,更多锁机制看此文 http://blog.csdn.net/samjustin1/article/details/52210125
5.findAndModify():When findAndModify()
includes the upsert: true
option and the query field(s) is not uniquely indexed, the method could insert a document multiple times in certain circumstances.Then, if these clients’ findAndModify()
methods finish the query
phase before any command starts the modify
phase, and there is no unique index on the name
field, the commands may all perform an upsert, creating multiple duplicate documents.To prevent the creation of multiple duplicate documents with the same name, create a unique index on the name
field.
6.replica set集群 ,基本配置操作见官网,https://docs.mongodb.com/manual/administration/replica-set-deployment/ ,通常建议将复制集成员数量设置为奇数,因为奇数可以让选举主节点进行的更平稳,如果只有两个实例时:当集群中仅有的2个实例挂掉一个,剩下的一个并不能判断自己的存活状况,因为也可能是自己跟网络断开了连接造成的。另外一个实例说不定还活得好好的呢。因此没有办法,暂时让自己成为Secondary活下去吧。Secondary结点默认不可读。注意事项见 http://www.cnblogs.com/yaoxing/p/mongodb-replica-set-setup.html MongoDb复制集原理:https://yq.aliyun.com/articles/64?spm=5176.100239.blogcont32434.18.6v2T2H
7.mongo如何控制并发,用乐观锁,大多是基于数据版本 Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来 实现。提交版本必须大于记 录当前版本才能执行更新
MongoDB allows multiple clients to read and write the same data. In order to ensure consistency, it uses locking and other concurrency control measures to prevent multiple clients from modifying the same piece of data simultaneously. Together, these mechanisms guarantee that all writes to a single document occur either in full or not at all and that clients never see an inconsistent view of the data.
10.在本机搭建简单的Sharded cluster 参照此文 http://www.jb51.net/article/87916.htm
其中 步骤2 要加 --configsvr,要不然会报如下错
{
"ok" : 0,
"errmsg" : "Surprised to discover that localhost:27027 does not believe it is a config server",
"code" : 72
} :
--fork 是以守护进程启动server,mkdir -p参数是递归建目录
sh.addShard('sh0/localhost:37017,localhost:37018,localhost:37019')添加分片副本集
sh.shardCollection( "test.users", { id: "hashed" } ) 这个操作将 test 数据库的 users 集合,使用 id 字段作为哈希片键开启分片.
11.ReadConcern:支持『local』和『majority』2个级别。local 即普通的 read,majority 级别保证应用读到的数据已经成功写入到了复制集的大多数成员。
12.MongoDB Sharded Cluster 路由策略 https://yq.aliyun.com/articles/58689?spm=5176.8091938.0.0.UemLKg
13.关于MongoDB Sharding,你应该知道的 http://www.mongoing.com/archives/3397
当进行写操作的时候会加写锁,这个时候不能进行其他的读操作和写操作。按照这个道理,因为写操作会阻塞读操作,所以是不会出现脏读的。
16.但是mongodb在分片和复制集的时候会产生脏读
mongo副本集中:使用readConcern
readConcern级别:
"local":默认。该查询返回实例的最新数据。不保证数据已写入大多数副本集成员(即可以回滚)。
"majority":该查询会将实例的最新数据确认为已写入副本集中的大多数成员。要使用majority级别,您必须使用--enableMajorityReadConcern命令行选项启动mongod实例(如果使用配置文件,则将replication.enableMajorityReadConcern设置为true)。
"linearizable"(add in version3.4):该查询返回反映所有成功写入的数据。
17.因为Mongdb没有事务,所以也就不存在幻读和不可重复读的定义了
18.findAndModify可以保证修改+返回结果(修改前或者修改后都可以)这两个步骤的原子性。
writeConcern:{ w: <value>, j: <boolean>, wtimeout: <number> }
write concern:0(Unacknowledged driver调用了getLastError()之后,mongod立刻返回结果,然后才实际进行写操作。所以getLastError()的返回值一定是null,即使之后的Apply发生了错误,driver也不知道。使用这个级别的write concern,driver的写入调用立刻返回,所以性能是最好的,但是可靠性是最差的,因此并不推荐使用。
其实还有一个w:-1的级别,是error ignored,基本上和w:0差不多。区别在于,w:-1不会捕获任何错误,而w:0可以捕获network error
write concern:1 ,和Unacknowledged的区别是,现在mongod只有在Apply(实际写入操作)完成之后,才会返回getLastError()的响应。所以如果写入时发生错误,driver就能捕获到,并进行处理。这个级别的write concern具备基本可靠性,也是目前mongodb的默认设置级别
write concern:1 & journal:true(Jounaled):mongodb的Apply操作,是将数据写入内存,定期通过fsync写入硬盘。如果在Apply之后,fsync之前mongod挂了,那持久化实际上是失败的。但是在w:1的级别下,driver无法捕获到这种情况下的error(因为response在apply之后就已经返回到driver)
使用Journal机制:写操作在写入内存之后,还会写到journal文件中,实实在在的把journal落盘以后才会返回。
MongoDB并不会对每一个操作都立即刷盘,而是会等最多30ms,把30ms内的写操作集中到一起,采用顺序追加的方式写入到盘里。在这30ms内客户端线程会处于等待状态。这样对于单个操作的总体响应时间将有所延长,但对于高并发的场景,综合下来平均吞吐能力和响应时间不会有太大的影响
write concern:2(Replica Acknowledged)
这个级别下,只有secondary从primary完成了复制之后,getLastError()的结果才会返回。也可以同时设置journal:true或j:true,则还要等journal写入也成功后才会返回。但是注意,只要primary的journal写入就会返回,而不需要等待secondary的journal也写入。类似的也可以设置w:3,表示至少要有3个节点有数据;或者w:majority,表示>1/2的节点有数据20.并发写入用排他锁,mongoose的_v应该就是这个实现
读操作MongoDB快的原因是: 1)MongoDB的设计要求你常用的数据(working set)可以在内存里装下。这样大部分操作只需要读内存,自然很快。 2)文档性模式设计一般会是的你所需要的数据都相对集中在一起(内存或硬盘),大家知道硬盘读写耗时最多是随机读写所产生的磁头定位时间,数据集中在一起则减少了关系性数据库需要从各个地方去把数据找过来(然后Join)所耗费的随机读时间
另外一个就是如@王子亭所提到的Mongo是分布式集群所以可以平行扩展。目前一般的百万次并发量都是通过几十上百个节点的集群同时实现。这一点MySQL基本无法做到(或者要花很大定制的代价)