mongodb学习笔记

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.

8.多文档的更新用$isolated操作符 ,能够阻止其它的进程在写操作的过程中修改第一个文档。这样就保证没有客户端能够看到修改,直到写操作完成或者出错。但是不会回滚


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


14.mongoose创建文档时,默认自带 _v 字段: 简单说这个字段用来在 save 文档时作为一个查询条件,以免在从「取出数据」到「save 数据」这段时间里,数据被其他进程修改,导致最后修改出现冲突。
15. Mongodb使用读写锁来来控制并发操作: 当进行读操作的时候会加读锁,这个时候其他读操作可以也获得读锁。但是不能或者写锁。

当进行写操作的时候会加写锁,这个时候不能进行其他的读操作和写操作。按照这个道理,因为写操作会阻塞读操作,所以是不会出现脏读的。


16.但是mongodb在分片和复制集的时候会产生脏读

 mongo副本集中:使用readConcern

readConcern级别:

"local":默认。该查询返回实例的最新数据。不保证数据已写入大多数副本集成员(即可以回滚)。

"majority":该查询会将实例的最新数据确认为已写入副本集中的大多数成员。要使用majority级别,您必须使用--enableMajorityReadConcern命令行选项启动mongod实例(如果使用配置文件,则将replication.enableMajorityReadConcern设置为true)。

"linearizable"(add in version3.4):该查询返回反映所有成功写入的数据。

17.因为Mongdb没有事务,所以也就不存在幻读和不可重复读的定义了

18.findAndModify可以保证修改+返回结果(修改前或者修改后都可以)这两个步骤的原子性。

19.write concern

写关注。

在写操作中加入:

writeConcern:{ w: <value>, j: <boolean>, wtimeout: <number> }

所有的mongodb driver,在执行一个写操作(insert、update、delete)之后,都会立刻调用db.getLastError()方法。这样才有机会知道刚才的写操作是否成功,如果捕获到错误,就可以进行相应的处理。处理逻辑也是完全由client决定的,比如写入日志、抛出错误、等待一段时间再次尝试写入等。作为mongodb server并不关心,server只负责通知client发生了错误对写操作的保证,级别越高,可靠性越高但是性能越低

write concern:0Unacknowledged driver调用了getLastError()之后,mongod立刻返回结果,然后才实际进行写操作。所以getLastError()的返回值一定是null,即使之后的Apply发生了错误,driver也不知道。使用这个级别的write concerndriver的写入调用立刻返回,所以性能是最好的,但是可靠性是最差的,因此并不推荐使用。
其实还有一个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:trueJounaled:mongodbApply操作,是将数据写入内存,定期通过fsync写入硬盘。如果在Apply之后,fsync之前mongod挂了,那持久化实际上是失败的。但是在w:1的级别下,driver无法捕获到这种情况下的error(因为responseapply之后就已经返回到driver
使用Journal机制:写操作在写入内存之后,还会写到journal文件中,实实在在的把journal落盘以后才会返回。
MongoDB
并不会对每一个操作都立即刷盘,而是会等最多30ms,把30ms内的写操作集中到一起,采用顺序追加的方式写入到盘里。在这30ms内客户端线程会处于等待状态。这样对于单个操作的总体响应时间将有所延长,但对于高并发的场景,综合下来平均吞吐能力和响应时间不会有太大的影响

write concern:2Replica Acknowledged

这个级别只在replica set的部署模式下生效

这个级别下,只有secondaryprimary完成了复制之后,getLastError()的结果才会返回。也可以同时设置journal:truej:true,则还要等journal写入也成功后才会返回。但是注意,只要primaryjournal写入就会返回,而不需要等待secondaryjournal也写入。类似的也可以设置w:3,表示至少要有3个节点有数据;或者w:majority,表示>1/2的节点有数据

注意

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

journal无论如何都是建议打开的,设置j:true,只是说driver调用getLastError()之后是否要等待journal写入完成再返回。并不是说不设置j:true就关闭了server端的journal

一般来说,MongoDB建议在集群中使用 {w: "majority"} 设置。在一个集群是健壮的部署的情况下(如:足够网络带宽,机器没有满负荷),这个可以满足绝大部分数据安全的要求,因为MongoDB的复制在正常情况下是毫秒级别的,往往在Journal刷盘之前已经复制到从节点了。如果你追求完美,那么可以再进一步使用{j:1}

20.并发写入用排他锁,mongoose的_v应该就是这个实现
21. 写操作MongoDB比传统数据库快的根本原因是Mongo使用的内存映射技术 - 写入数据时候只要在内存里完成就可以返回给应用程序,这样并发量自然就很高。而保存到硬体的操作则在后台异步完成。注意MongoDB在2.4就已经是默认安全写了(具体实现在驱动程序里),所以楼上有同学的回答说是”默认不安全“应该是基于2.2或之前版本的。

读操作MongoDB快的原因是: 1)MongoDB的设计要求你常用的数据(working set)可以在内存里装下。这样大部分操作只需要读内存,自然很快。 2)文档性模式设计一般会是的你所需要的数据都相对集中在一起(内存或硬盘),大家知道硬盘读写耗时最多是随机读写所产生的磁头定位时间,数据集中在一起则减少了关系性数据库需要从各个地方去把数据找过来(然后Join)所耗费的随机读时间

另外一个就是如@王子亭所提到的Mongo是分布式集群所以可以平行扩展。目前一般的百万次并发量都是通过几十上百个节点的集群同时实现。这一点MySQL基本无法做到(或者要花很大定制的代价)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值